···3 * @param signal - an aptional abort signal, to cancel the sleep
4 * @returns a promise that resolves after given amount of time, and is interruptable with an abort signal.
5 */
6-export function sleep(ms: number, signal?: AbortSignal): Promise<void> {
7 signal?.throwIfAborted()
8-9- // not sure why this error is coming up
1011 const {resolve, reject, promise} = Promise.withResolvers<void>()
12 const timeout = setTimeout(resolve, ms)
13014 if (!signal) return promise
1516 const abortHandler = () => {
···18 reject(signal.reason)
19 }
2021- signal.addEventListener('abort', abortHandler)
22- return promise.finally(() => {
00023 signal.removeEventListener('abort', abortHandler)
24- })
0000000000000000000025}
···3 * @param signal - an aptional abort signal, to cancel the sleep
4 * @returns a promise that resolves after given amount of time, and is interruptable with an abort signal.
5 */
6+export async function sleep(ms: number, signal?: AbortSignal): Promise<void> {
7 signal?.throwIfAborted()
0089 const {resolve, reject, promise} = Promise.withResolvers<void>()
10 const timeout = setTimeout(resolve, ms)
1112+ // without the signal, we can't cancel it, so just let the timeout resolve
13 if (!signal) return promise
1415 const abortHandler = () => {
···17 reject(signal.reason)
18 }
1920+ try {
21+ signal.addEventListener('abort', abortHandler)
22+ await promise
23+ return
24+ } finally {
25 signal.removeEventListener('abort', abortHandler)
26+ }
27+}
28+29+export function backoff(options?: {maxAttempts?: number; baseDelay?: number; maxDelay?: number}) {
30+ const maxAttempts = options?.maxAttempts ?? 10
31+ const baseDelay = options?.baseDelay ?? 1000
32+ const maxDelay = options?.maxDelay ?? 30_000
33+34+ let attempts = 0
35+ const nextDelay = () => {
36+ return attempts === 0
37+ ? attempts++ // immediate at 0
38+ : Math.min(baseDelay * Math.pow(2, attempts++ - 1), maxDelay)
39+ }
40+41+ return async (signal?: AbortSignal) => {
42+ signal?.throwIfAborted()
43+ if (attempts > maxAttempts) throw new Error('exceeded max attempts!')
44+45+ await sleep(nextDelay(), signal)
46+ }
47}