diff --git a/packages/gateway-client/src/client.ts b/packages/gateway-client/src/client.ts index 1e7beef4dd2b..6181e18d95dd 100644 --- a/packages/gateway-client/src/client.ts +++ b/packages/gateway-client/src/client.ts @@ -1389,7 +1389,7 @@ export class GatewayClient { typeof rawMinInterval === "number" && Number.isFinite(rawMinInterval) ? Math.max(1, Math.min(30_000, rawMinInterval)) : 1000; - const interval = Math.max(this.tickIntervalMs, minInterval); + const interval = resolveSafeTimeoutDelayMs(Math.max(this.tickIntervalMs, minInterval)); this.tickTimer = setInterval(() => { if (this.closed) { return; diff --git a/packages/gateway-client/src/client.watchdog.test.ts b/packages/gateway-client/src/client.watchdog.test.ts index 4a767b23adb8..f8adc465793d 100644 --- a/packages/gateway-client/src/client.watchdog.test.ts +++ b/packages/gateway-client/src/client.watchdog.test.ts @@ -253,6 +253,39 @@ describe("GatewayClient", () => { } }); + test("clamps oversized tick watchdog intervals before scheduling", () => { + vi.useFakeTimers(); + try { + const setIntervalSpy = vi.spyOn(globalThis, "setInterval"); + const client = new GatewayClient({ + tickWatchMinIntervalMs: 5, + }); + Object.assign( + client as unknown as { ws: unknown; tickIntervalMs: number; lastTick: number }, + { + ws: { + readyState: WebSocket.OPEN, + send: vi.fn(), + close: vi.fn(), + }, + tickIntervalMs: Number.MAX_SAFE_INTEGER, + lastTick: Date.now(), + }, + ); + + ( + client as unknown as { + startTickWatch: () => void; + } + ).startTickWatch(); + + expect(setIntervalSpy).toHaveBeenCalledWith(expect.any(Function), MAX_SAFE_TIMEOUT_DELAY_MS); + client.stop(); + } finally { + vi.useRealTimers(); + } + }); + test("times out unresolved requests and clears pending state", async () => { vi.useFakeTimers(); try {