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); + }); });