From 78469b689b381ab890cf04a522f87d55e4540f43 Mon Sep 17 00:00:00 2001 From: ch-z-hc <45302000+ch-z-hc@users.noreply.github.com> Date: Tue, 13 Oct 2026 22:10:20 +0800 Subject: [PATCH] fix: cap polling sleep at the remaining deadline --- src/polling/poll.ts | 2 +- test/polling/poll.test.ts | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/polling/poll.ts b/src/polling/poll.ts index 06ca59fc..7619ea48 100644 --- a/src/polling/poll.ts +++ b/src/polling/poll.ts @@ -49,7 +49,7 @@ export async function poll(config: Config, opts: PollOptions): Promise { ); } - await new Promise(r => setTimeout(r, opts.intervalSec * 1000)); + await new Promise(r => setTimeout(r, Math.min(opts.intervalSec * 1000, Math.max(0, deadline - Date.now())))); } } finally { spinner.stop(); diff --git a/test/polling/poll.test.ts b/test/polling/poll.test.ts index 27f25540..efb5db6d 100644 --- a/test/polling/poll.test.ts +++ b/test/polling/poll.test.ts @@ -147,4 +147,20 @@ describe('poll', () => { expect(callCount).toBe(1); expect(result).toBeDefined(); }); + + it('does not sleep for the full polling interval when the timeout is shorter', async () => { + setFetch(mock(() => Promise.resolve(jsonRes({ status: 'Processing' })))); + const { poll } = await import('../../src/polling/poll'); + const started = performance.now(); + + await expect(poll(baseConfig, { + url: 'https://api.mmx.io/poll', + intervalSec: 1.5, + timeoutSec: 0.05, + isComplete: () => false, + isFailed: () => false, + })).rejects.toThrow('Polling timed out'); + + expect(performance.now() - started).toBeLessThan(1000); + }); });