Suite of AT Protocol TypeScript libraries built on web standards
21
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 59 lines 1.5 kB view raw
1import { wait } from "./util.ts"; 2 3export type RetryOptions = { 4 maxRetries?: number; 5 getWaitMs?: (n: number) => number | null; 6}; 7 8export async function retry<T>( 9 fn: () => Promise<T> | T, 10 opts: RetryOptions & { 11 retryable?: (err: unknown) => boolean; 12 } = {}, 13): Promise<T> { 14 const { maxRetries = 3, retryable = () => true, getWaitMs = backoffMs } = 15 opts; 16 let retries = 0; 17 let doneError: unknown; 18 while (!doneError) { 19 try { 20 return await fn(); 21 } catch (err) { 22 const waitMs = getWaitMs(retries); 23 const willRetry = retries < maxRetries && waitMs !== null && 24 retryable(err); 25 if (willRetry) { 26 retries += 1; 27 if (waitMs !== 0) { 28 await wait(waitMs); 29 } 30 } else { 31 doneError = err; 32 } 33 } 34 } 35 throw doneError; 36} 37 38export function createRetryable(retryable: (err: unknown) => boolean): { 39 <T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T>; 40} { 41 return <T>(fn: () => Promise<T>, opts?: RetryOptions) => 42 retry(fn, { ...opts, retryable }); 43} 44 45export function backoffMs(n: number, multiplier = 100, max = 1000): number { 46 const exponentialMs = Math.pow(2, n) * multiplier; 47 const ms = Math.min(exponentialMs, max); 48 return jitter(ms); 49} 50 51function jitter(value: number) { 52 const delta = value * 0.15; 53 return value + randomRange(-delta, delta); 54} 55 56function randomRange(from: number, to: number) { 57 const rand = Math.random() * (to - from); 58 return rand + from; 59}