import {sleep} from "./sleep.js";
export type RetryOptions = {
/**
* The maximum amount of times to retry the operation. Default is 5
*/
retries?: number;
/**
* An optional Function that is invoked after the provided callback throws
* It expects a boolean to know if it should retry or not
* Useful to make retrying conditional on the type of error thrown
*/
shouldRetry?: (lastError: Error) => boolean;
/**
* Milliseconds to wait before retrying again
*/
retryDelay?: number;
};
/**
* Retry a given function on error.
* @param fn Async callback to retry. Invoked with 1 parameter
* A Number identifying the attempt. The absolute first attempt (before any retries) is 1
* @param opts
*/
export async function retry(fn: (attempt: number) => A | Promise, opts?: RetryOptions): Promise {
const maxRetries = opts?.retries ?? 5;
const shouldRetry = opts?.shouldRetry;
let lastError: Error = Error("RetryError");
for (let i = 1; i <= maxRetries; i++) {
try {
return await fn(i);
} catch (e) {
lastError = e as Error;
if (shouldRetry && !shouldRetry(lastError)) {
break;
} else if (opts?.retryDelay !== undefined) {
await sleep(opts?.retryDelay);
}
}
}
throw lastError;
}