Improve error handling

This commit is contained in:
tdurieux
2026-05-06 12:26:12 +03:00
parent c4182b5b2a
commit e1cf8e3a00
2 changed files with 31 additions and 11 deletions
+6 -7
View File
@@ -59,13 +59,12 @@ function getRedis(): RedisClientType | null {
}, },
}) as RedisClientType; }) as RedisClientType;
redisClient.on("error", () => { redisClient.on("error", () => {
if (!redisDisabled) { if (redisDisabled) return;
redisDisabled = true; redisDisabled = true;
try { const c = redisClient;
redisClient?.disconnect(); redisClient = null;
} catch { if (c?.isOpen) {
/* ignore */ c.disconnect().catch(() => {});
}
} }
}); });
redisClient.connect().catch(() => { redisClient.connect().catch(() => {
+25 -4
View File
@@ -183,14 +183,35 @@ export default class GitHubStream extends GitHubBase {
const stream1 = content.pipe(new stream.PassThrough()); const stream1 = content.pipe(new stream.PassThrough());
const stream2 = content.pipe(new stream.PassThrough()); const stream2 = content.pipe(new stream.PassThrough());
// Safety net: guarantee an `error` listener exists on both branches
// before any error can be emitted. storage.write attaches its listener
// only after an `await mk(...)`, and the route handler attaches its
// listener after awaiting this function — both leave a window where
// an upstream error would have no listener and escalate to
// uncaughtException, crashing the streamer.
const noop = () => {};
stream1.on("error", noop);
stream2.on("error", noop);
content.on("error", (error) => { content.on("error", (error) => {
error = new AnonymousError("file_not_found", { const httpStatus =
httpStatus: (error as { status?: number; httpStatus?: number }).status || (error as { httpStatus?: number }).httpStatus, (error as { response?: { statusCode?: number } })?.response
?.statusCode ??
(error as { status?: number })?.status ??
(error as { httpStatus?: number })?.httpStatus;
const code =
httpStatus === 422
? "file_too_big"
: httpStatus === 403
? "file_not_accessible"
: "file_not_found";
const wrapped = new AnonymousError(code, {
httpStatus,
cause: error as Error, cause: error as Error,
object: filePath, object: filePath,
}); });
stream1.emit("error", error); stream1.destroy(wrapped);
stream2.emit("error", error); stream2.destroy(wrapped);
}); });
storage.write(repoId, filePath, stream1, this.type); storage.write(repoId, filePath, stream1, this.type);