fix(regression): fail discord startup on reconnect exhaustion

This commit is contained in:
Tak Hoffman
2026-03-27 16:20:02 -05:00
parent c125c33724
commit 9134dbd252
2 changed files with 38 additions and 3 deletions

View File

@@ -855,6 +855,37 @@ describe("runDiscordGatewayLifecycle", () => {
expect(runtimeError).toHaveBeenCalledWith(expect.stringContaining("Max reconnect attempts"));
});
it("rejects reconnect-exhausted queued before startup when shutdown has not begun", async () => {
const { runDiscordGatewayLifecycle } = await import("./provider.lifecycle.js");
const pendingGatewayEvents: DiscordGatewayEvent[] = [];
const emitter = new EventEmitter();
const gateway: MockGateway = {
isConnected: true,
options: { intents: 0, reconnect: { maxAttempts: 50 } } as GatewayPlugin["options"],
disconnect: vi.fn(),
connect: vi.fn(),
emitter,
};
getDiscordGatewayEmitterMock.mockReturnValueOnce(emitter);
const { lifecycleParams } = createLifecycleHarness({
gateway,
pendingGatewayEvents,
});
pendingGatewayEvents.push(
createGatewayEvent(
"reconnect-exhausted",
"Max reconnect attempts (0) reached after code 1005",
),
);
await expect(runDiscordGatewayLifecycle(lifecycleParams)).rejects.toThrow(
"Max reconnect attempts",
);
});
it("does not push connected: true when abortSignal is already aborted", async () => {
const { runDiscordGatewayLifecycle } = await import("./provider.lifecycle.js");
const emitter = new EventEmitter();

View File

@@ -83,9 +83,13 @@ export async function runDiscordGatewayLifecycle(params: {
return "continue";
}
// Don't throw for expected shutdown events. `reconnect-exhausted` can be
// queued before teardown flips `lifecycleStopping`, so treat it as a
// graceful stop here and let the health monitor own reconnect behavior.
if (event.type === "disallowed-intents" || event.type === "reconnect-exhausted") {
// queued just before an abort-driven shutdown flips `lifecycleStopping`,
// so only suppress it when shutdown is already underway.
if (
event.type === "disallowed-intents" ||
(event.type === "reconnect-exhausted" &&
(lifecycleStopping || params.abortSignal?.aborted === true))
) {
return "stop";
}
throw event.err;