Skip to content

Commit 84d3b65

Browse files
krassxclaude
andcommitted
test(node): de-flake the real-worker event-loop-watchdog e2e on CI
The watchdog worker spawns asynchronously and can only observe a block that STARTS after it is polling. The test's single fixed 60ms "spin-up" wait is racy on a loaded CI runner where worker_threads startup exceeds it — the block then lands before monitoring begins and is never seen, so onHang never fires and vi.waitFor times out (the CI failure). Block the loop in ~120ms bursts and retry until one is caught (vi.waitFor, 8s ceiling): converges as soon as the worker is alive whatever the startup latency, and stays ~sub-second on a healthy runner. No production change; node coverage unchanged (100% line/fn/stmt, 98.48% branch). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 1558f59 commit 84d3b65

1 file changed

Lines changed: 18 additions & 7 deletions

File tree

‎packages/node/src/event-loop-watchdog.test.ts‎

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,24 @@ describe('createEventLoopWatchdog', () => {
250250
heartbeatIntervalMs: 20, // < fairMs
251251
});
252252
wd.start();
253-
await new Promise((r) => setTimeout(r, 60)); // let the heartbeat tick + worker spin up
254-
const end = Date.now() + 150; // block the loop ~150ms — the heartbeat timer can't fire
255-
while (Date.now() < end) {
256-
// busy spin
257-
}
258-
await vi.waitFor(() => expect(onHang).toHaveBeenCalled(), { timeout: 2000 });
253+
// The worker is spawned ASYNCHRONOUSLY (worker_threads startup) and can only observe a block
254+
// that happens AFTER it is polling. A single fixed "spin-up" wait is racy on a loaded CI runner
255+
// where startup routinely exceeds it (the block then lands before monitoring begins and is never
256+
// seen). So block the loop in ~120ms bursts and retry until one burst is caught — converging as
257+
// soon as the worker is alive, whenever that is, while staying fast on a healthy runner.
258+
await vi.waitFor(
259+
() => {
260+
if (onHang.mock.calls.length === 0) {
261+
const end = Date.now() + 120; // > fairMs (60): a live worker MUST see this stall
262+
while (Date.now() < end) {
263+
// busy spin — freeze the loop so the heartbeat timer can't refresh the shared buffer
264+
}
265+
}
266+
expect(onHang).toHaveBeenCalled();
267+
},
268+
{ timeout: 8000, interval: 50 },
269+
);
259270
expect(['fair', 'medium', 'severe']).toContain(onHang.mock.calls[0]?.[0]);
260271
wd.stop();
261-
});
272+
}, 12_000);
262273
});

0 commit comments

Comments
 (0)