Last active
February 6, 2024 15:31
-
-
Save raynirola/9e4e4770d16ac539e31564e456eb5aa0 to your computer and use it in GitHub Desktop.
Simple retry helper with typescript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Args<T> = { | |
fn: () => Promise<T>; | |
retries: number; | |
delay: number; | |
backoffFactor: number; | |
onFailedAttempt?: (error: unknown, attemptNumber: number) => Promise<void>; | |
}; | |
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); | |
class RetryExhaustedError extends Error { | |
constructor() { | |
super("Retry attempts have been exhausted"); | |
this.name = "RetryExhaustedError"; | |
} | |
} | |
class OnFailedAttemptError extends Error { | |
constructor(error: unknown) { | |
super( | |
`Error in onFailedAttempt: ${ | |
error instanceof Error ? error.message : "Unknown error" | |
}` | |
); | |
this.name = "OnFailedAttemptError"; | |
} | |
} | |
async function retry<T>( | |
{ | |
fn, | |
retries = 3, | |
delay = 1000, | |
backoffFactor = 2, | |
onFailedAttempt, | |
}: Args<T>, | |
attempt = 1 | |
): Promise<T> { | |
try { | |
return await fn(); | |
} catch (_aError) { | |
if (attempt > retries) throw new RetryExhaustedError(); | |
try { | |
await onFailedAttempt?.(_aError, attempt); | |
} catch (_hError) { | |
throw new OnFailedAttemptError(_hError); | |
} | |
await sleep(delay * Math.pow(backoffFactor, attempt - 1)); | |
return await retry( | |
{ fn, retries, delay, backoffFactor, onFailedAttempt }, | |
attempt + 1 | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment