Skip to content

Commit e1cf8e3

Browse files
committed
Improve error handling
1 parent c4182b5 commit e1cf8e3

2 files changed

Lines changed: 31 additions & 11 deletions

File tree

src/core/logger.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,12 @@ function getRedis(): RedisClientType | null {
5959
},
6060
}) as RedisClientType;
6161
redisClient.on("error", () => {
62-
if (!redisDisabled) {
63-
redisDisabled = true;
64-
try {
65-
redisClient?.disconnect();
66-
} catch {
67-
/* ignore */
68-
}
62+
if (redisDisabled) return;
63+
redisDisabled = true;
64+
const c = redisClient;
65+
redisClient = null;
66+
if (c?.isOpen) {
67+
c.disconnect().catch(() => {});
6968
}
7069
});
7170
redisClient.connect().catch(() => {

src/core/source/GitHubStream.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,35 @@ export default class GitHubStream extends GitHubBase {
183183
const stream1 = content.pipe(new stream.PassThrough());
184184
const stream2 = content.pipe(new stream.PassThrough());
185185

186+
// Safety net: guarantee an `error` listener exists on both branches
187+
// before any error can be emitted. storage.write attaches its listener
188+
// only after an `await mk(...)`, and the route handler attaches its
189+
// listener after awaiting this function — both leave a window where
190+
// an upstream error would have no listener and escalate to
191+
// uncaughtException, crashing the streamer.
192+
const noop = () => {};
193+
stream1.on("error", noop);
194+
stream2.on("error", noop);
195+
186196
content.on("error", (error) => {
187-
error = new AnonymousError("file_not_found", {
188-
httpStatus: (error as { status?: number; httpStatus?: number }).status || (error as { httpStatus?: number }).httpStatus,
197+
const httpStatus =
198+
(error as { response?: { statusCode?: number } })?.response
199+
?.statusCode ??
200+
(error as { status?: number })?.status ??
201+
(error as { httpStatus?: number })?.httpStatus;
202+
const code =
203+
httpStatus === 422
204+
? "file_too_big"
205+
: httpStatus === 403
206+
? "file_not_accessible"
207+
: "file_not_found";
208+
const wrapped = new AnonymousError(code, {
209+
httpStatus,
189210
cause: error as Error,
190211
object: filePath,
191212
});
192-
stream1.emit("error", error);
193-
stream2.emit("error", error);
213+
stream1.destroy(wrapped);
214+
stream2.destroy(wrapped);
194215
});
195216

196217
storage.write(repoId, filePath, stream1, this.type);

0 commit comments

Comments
 (0)