mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix: guard isConnected check against already-aborted signal
When abortSignal is already aborted at lifecycle start, onAbort() fires synchronously and pushes connected: false. Without a lifecycleStopping guard, the subsequent gateway.isConnected check could push a spurious connected: true, contradicting the shutdown. Adds !lifecycleStopping to the isConnected guard and a test verifying no connected: true is emitted when the signal is pre-aborted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Peter Steinberger
parent
d9119f0791
commit
17b40c4a59
@@ -408,4 +408,40 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it("does not push connected: true when abortSignal is already aborted", async () => {
|
||||
const { runDiscordGatewayLifecycle } = await import("./provider.lifecycle.js");
|
||||
const emitter = new EventEmitter();
|
||||
const gateway = {
|
||||
isConnected: true,
|
||||
options: { reconnect: { maxAttempts: 3 } },
|
||||
disconnect: vi.fn(),
|
||||
connect: vi.fn(),
|
||||
emitter,
|
||||
};
|
||||
getDiscordGatewayEmitterMock.mockReturnValueOnce(emitter);
|
||||
|
||||
const abortController = new AbortController();
|
||||
abortController.abort();
|
||||
|
||||
const statusUpdates: Array<Record<string, unknown>> = [];
|
||||
const statusSink = (patch: Record<string, unknown>) => {
|
||||
statusUpdates.push({ ...patch });
|
||||
};
|
||||
|
||||
const { lifecycleParams } = createLifecycleHarness({ gateway });
|
||||
lifecycleParams.abortSignal = abortController.signal;
|
||||
(lifecycleParams as Record<string, unknown>).statusSink = statusSink;
|
||||
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
// onAbort should have pushed connected: false
|
||||
const connectedFalse = statusUpdates.find((s) => s.connected === false);
|
||||
expect(connectedFalse).toBeDefined();
|
||||
|
||||
// No connected: true should appear — the isConnected check must be
|
||||
// guarded by !lifecycleStopping to avoid contradicting the abort.
|
||||
const connectedTrue = statusUpdates.find((s) => s.connected === true);
|
||||
expect(connectedTrue).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -247,7 +247,10 @@ export async function runDiscordGatewayLifecycle(params: {
|
||||
// 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) {
|
||||
// Guard against lifecycleStopping: if the abortSignal was already aborted,
|
||||
// onAbort() ran synchronously above and pushed connected: false — don't
|
||||
// contradict it with a spurious connected: true.
|
||||
if (gateway?.isConnected && !lifecycleStopping) {
|
||||
const at = Date.now();
|
||||
pushStatus({
|
||||
connected: true,
|
||||
|
||||
Reference in New Issue
Block a user