import { sleep } from "./utils/sleep"; import { WaiterState } from "./waiter"; const exponentialBackoffWithJitter = (minDelay, maxDelay, attemptCeiling, attempt) => { if (attempt > attemptCeiling) return maxDelay; const delay = minDelay * 2 ** (attempt - 1); return randomInRange(minDelay, delay); }; const randomInRange = (min, max) => min + Math.random() * (max - min); export const runPolling = async ({ minDelay, maxDelay, maxWaitTime, abortController, client, abortSignal }, input, acceptorChecks) => { const { state, reason } = await acceptorChecks(client, input); if (state !== WaiterState.RETRY) { return { state, reason }; } let currentAttempt = 1; const waitUntil = Date.now() + maxWaitTime * 1000; const attemptCeiling = Math.log(maxDelay / minDelay) / Math.log(2) + 1; while (true) { if (abortController?.signal?.aborted || abortSignal?.aborted) { return { state: WaiterState.ABORTED }; } const delay = exponentialBackoffWithJitter(minDelay, maxDelay, attemptCeiling, currentAttempt); if (Date.now() + delay * 1000 > waitUntil) { return { state: WaiterState.TIMEOUT }; } await sleep(delay); const { state, reason } = await acceptorChecks(client, input); if (state !== WaiterState.RETRY) { return { state, reason }; } currentAttempt += 1; } };