From 2bdb2e8e02bbb0e226a3ba850d472a7b9091b2c2 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 30 May 2026 18:30:29 -0400 Subject: [PATCH] fix(gateway-client): clamp readiness intervals --- .../src/event-loop-ready.test.ts | 23 +++++++++++++++++++ .../gateway-client/src/event-loop-ready.ts | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/gateway-client/src/event-loop-ready.test.ts b/packages/gateway-client/src/event-loop-ready.test.ts index 9948c10de30..4081cac63b4 100644 --- a/packages/gateway-client/src/event-loop-ready.test.ts +++ b/packages/gateway-client/src/event-loop-ready.test.ts @@ -1,5 +1,6 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { waitForEventLoopReady } from "./event-loop-ready.js"; +import { MAX_SAFE_TIMEOUT_DELAY_MS } from "./timeouts.js"; describe("waitForEventLoopReady", () => { afterEach(() => { @@ -25,4 +26,26 @@ describe("waitForEventLoopReady", () => { checks: 2, }); }); + + it("clamps oversized readiness intervals before scheduling", async () => { + vi.useFakeTimers(); + const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout"); + + const readiness = waitForEventLoopReady({ + maxWaitMs: Number.MAX_SAFE_INTEGER, + intervalMs: Number.MAX_SAFE_INTEGER, + consecutiveReadyChecks: 1, + }); + + expect(setTimeoutSpy).toHaveBeenLastCalledWith(expect.any(Function), MAX_SAFE_TIMEOUT_DELAY_MS); + + await vi.advanceTimersByTimeAsync(1); + expect(setTimeoutSpy).toHaveBeenCalledTimes(1); + + await vi.advanceTimersByTimeAsync(MAX_SAFE_TIMEOUT_DELAY_MS - 1); + await expect(readiness).resolves.toMatchObject({ + ready: true, + checks: 1, + }); + }); }); diff --git a/packages/gateway-client/src/event-loop-ready.ts b/packages/gateway-client/src/event-loop-ready.ts index f732872b07b..f5c97cb0b20 100644 --- a/packages/gateway-client/src/event-loop-ready.ts +++ b/packages/gateway-client/src/event-loop-ready.ts @@ -31,7 +31,7 @@ export async function waitForEventLoopReady( const maxWaitMs = resolveFiniteTimeoutDelayMs(options.maxWaitMs, DEFAULT_MAX_WAIT_MS, { minMs: 0, }); - const intervalMs = resolvePositiveInteger(options.intervalMs, DEFAULT_INTERVAL_MS); + const intervalMs = resolveFiniteTimeoutDelayMs(options.intervalMs, DEFAULT_INTERVAL_MS); const driftThresholdMs = resolvePositiveInteger( options.driftThresholdMs, DEFAULT_DRIFT_THRESHOLD_MS,