mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 00:13:28 +00:00
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 runtimeError = vi.fn();
|
||||||
const runtimeExit = vi.fn();
|
const runtimeExit = vi.fn();
|
||||||
const releaseEarlyGatewayErrorGuard = vi.fn();
|
const releaseEarlyGatewayErrorGuard = vi.fn();
|
||||||
|
const statusSink = vi.fn();
|
||||||
const runtime: RuntimeEnv = {
|
const runtime: RuntimeEnv = {
|
||||||
log: runtimeLog,
|
log: runtimeLog,
|
||||||
error: runtimeError,
|
error: runtimeError,
|
||||||
@@ -89,6 +90,7 @@ describe("runDiscordGatewayLifecycle", () => {
|
|||||||
runtimeLog,
|
runtimeLog,
|
||||||
runtimeError,
|
runtimeError,
|
||||||
releaseEarlyGatewayErrorGuard,
|
releaseEarlyGatewayErrorGuard,
|
||||||
|
statusSink,
|
||||||
lifecycleParams: {
|
lifecycleParams: {
|
||||||
accountId: params?.accountId ?? "default",
|
accountId: params?.accountId ?? "default",
|
||||||
client: {
|
client: {
|
||||||
@@ -102,6 +104,7 @@ describe("runDiscordGatewayLifecycle", () => {
|
|||||||
threadBindings: { stop: threadStop },
|
threadBindings: { stop: threadStop },
|
||||||
pendingGatewayErrors: params?.pendingGatewayErrors,
|
pendingGatewayErrors: params?.pendingGatewayErrors,
|
||||||
releaseEarlyGatewayErrorGuard,
|
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 () => {
|
it("handles queued disallowed intents errors without waiting for gateway events", async () => {
|
||||||
const { runDiscordGatewayLifecycle } = await import("./provider.lifecycle.js");
|
const { runDiscordGatewayLifecycle } = await import("./provider.lifecycle.js");
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -244,6 +244,19 @@ export async function runDiscordGatewayLifecycle(params: {
|
|||||||
};
|
};
|
||||||
gatewayEmitter?.on("debug", onGatewayDebug);
|
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;
|
let sawDisallowedIntents = false;
|
||||||
const logGatewayError = (err: unknown) => {
|
const logGatewayError = (err: unknown) => {
|
||||||
if (params.isDisallowedIntentsError(err)) {
|
if (params.isDisallowedIntentsError(err)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user