From 9f2e25493b4e19c3747221deb2673a25aac45dd7 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Sun, 13 Sep 2026 06:47:05 +0100 Subject: [PATCH] test: poll for the first heartbeat tick instead of a fixed sleep The release job's prepublishOnly run failed this test on CI: it slept a fixed 120ms (6x the 20ms heartbeat interval) and checked once whether the registry's updatedAt had moved. A real setInterval carries no delivery guarantee under a busy scheduler, so a single fixed wait is a race against however loaded the runner happens to be at that instant, not against the interval itself. Polling in 20ms steps up to a 5s deadline only needs one tick to ever land, however late the runner makes it, so the test's outcome no longer depends on the runner's momentary CPU pressure. --- src/cc-peer-class.test.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/cc-peer-class.test.ts b/src/cc-peer-class.test.ts index 452948d..8be06b6 100644 --- a/src/cc-peer-class.test.ts +++ b/src/cc-peer-class.test.ts @@ -131,18 +131,25 @@ describe("CcPeer dependency-injected construction", () => { await peer.start(); const store = new FsRegistryStore({ homeDir: home }); const before = (await store.read(process.pid))?.updatedAt; - await new Promise((resolve) => { - const timer = setTimeout(() => { - resolve(); - }, 120); - timer.unref(); - }); - const after = (await store.read(process.pid))?.updatedAt; + expect(before).toBeDefined(); + // Polls for the first tick rather than sleeping a fixed multiple of heartbeatMs and checking once: a real setInterval has no delivery guarantee under a busy scheduler, so a single fixed wait is a race against however loaded the runner happens to be at that moment, whereas polling only needs one tick to ever land within the overall timeout, however late the runner makes it. + const deadline = Date.now() + 5_000; + let after: number | undefined; + do { + await new Promise((resolve) => { + const timer = setTimeout(resolve, 20); + timer.unref(); + }); + after = (await store.read(process.pid))?.updatedAt; + } while ( + (after === undefined || after <= (before ?? 0)) && + Date.now() < deadline + ); expect(after !== undefined && before !== undefined && after > before).toBe( true, ); await peer.stop(); - }); + }, 10_000); test("a heartbeat tick that fails to touch the registry is swallowed", async () => { const home = await tempHome();