fix(discord): push connected status when gateway is already connected at lifecycle start
When the Discord gateway completes its READY handshake before `runDiscordGatewayLifecycle` registers its debug event listener, the initial "WebSocket connection opened" event is missed. This leaves `connected` as undefined in the channel runtime, causing the health monitor to treat the channel as "stuck" and restart it every check cycle. Check `gateway.isConnected` immediately after registering the debug listener and push the initial connected status if the gateway is already connected. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Peter Steinberger
parent
586f057c24
commit
d9119f0791
@@ -77,6 +77,7 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
const runtimeError = vi.fn();
|
||||
const runtimeExit = vi.fn();
|
||||
const releaseEarlyGatewayErrorGuard = vi.fn();
|
||||
const statusSink = vi.fn();
|
||||
const runtime: RuntimeEnv = {
|
||||
log: runtimeLog,
|
||||
error: runtimeError,
|
||||
@@ -89,6 +90,7 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
runtimeLog,
|
||||
runtimeError,
|
||||
releaseEarlyGatewayErrorGuard,
|
||||
statusSink,
|
||||
lifecycleParams: {
|
||||
accountId: params?.accountId ?? "default",
|
||||
client: {
|
||||
@@ -102,6 +104,7 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
threadBindings: { stop: threadStop },
|
||||
pendingGatewayErrors: params?.pendingGatewayErrors,
|
||||
releaseEarlyGatewayErrorGuard,
|
||||
statusSink,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -203,6 +206,26 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("pushes connected status when gateway is already connected at lifecycle start", async () => {
|
||||
const { runDiscordGatewayLifecycle } = await import("./provider.lifecycle.js");
|
||||
const { emitter, gateway } = createGatewayHarness();
|
||||
gateway.isConnected = true;
|
||||
getDiscordGatewayEmitterMock.mockReturnValueOnce(emitter);
|
||||
|
||||
const { lifecycleParams, statusSink } = createLifecycleHarness({ gateway });
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
const connectedCall = statusSink.mock.calls.find(
|
||||
([patch]: [Record<string, unknown>]) => patch.connected === true,
|
||||
);
|
||||
expect(connectedCall).toBeDefined();
|
||||
expect(connectedCall![0]).toMatchObject({
|
||||
connected: true,
|
||||
lastDisconnect: null,
|
||||
});
|
||||
expect(connectedCall![0].lastConnectedAt).toBeTypeOf("number");
|
||||
});
|
||||
|
||||
it("handles queued disallowed intents errors without waiting for gateway events", async () => {
|
||||
const { runDiscordGatewayLifecycle } = await import("./provider.lifecycle.js");
|
||||
const {
|
||||
|
||||
@@ -244,6 +244,19 @@ export async function runDiscordGatewayLifecycle(params: {
|
||||
};
|
||||
gatewayEmitter?.on("debug", onGatewayDebug);
|
||||
|
||||
// If the gateway is already connected when the lifecycle starts (the
|
||||
// "WebSocket connection opened" debug event was emitted before we
|
||||
// registered the listener above), push the initial connected status now.
|
||||
if (gateway?.isConnected) {
|
||||
const at = Date.now();
|
||||
pushStatus({
|
||||
connected: true,
|
||||
lastEventAt: at,
|
||||
lastConnectedAt: at,
|
||||
lastDisconnect: null,
|
||||
});
|
||||
}
|
||||
|
||||
let sawDisallowedIntents = false;
|
||||
const logGatewayError = (err: unknown) => {
|
||||
if (params.isDisallowedIntentsError(err)) {
|
||||
|
||||
Reference in New Issue
Block a user