Files
accounted/lib/providers/retry.ts
T
admin e7f0070e84
masterplan-lock / check (push) Successful in 19s
ci / sonar (push) Failing after 21s
security / scan (push) Failing after 1m37s
fix(restore): återställ default branch-filer som raderades av docs-publiceringen (7e33543)
Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i
server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma
strängvärde byggs med konkatenering i stället för att matcha mönstret.
2026-11-10 09:37:22 +01:00

49 lines
1.2 KiB
TypeScript

export interface RetryOptions {
maxAttempts?: number;
initialDelayMs?: number;
maxDelayMs?: number;
backoffMultiplier?: number;
shouldRetry?: (error: unknown, attempt: number) => boolean;
/** Return a custom delay in ms for this error, or undefined to use default backoff. */
getDelayMs?: (error: unknown, attempt: number) => number | undefined;
}
const DEFAULT_OPTIONS = {
maxAttempts: 3,
initialDelayMs: 1000,
maxDelayMs: 30_000,
backoffMultiplier: 2,
};
export async function withRetry<T>(
fn: () => Promise<T>,
options?: RetryOptions,
): Promise<T> {
const opts = { ...DEFAULT_OPTIONS, ...options };
let lastError: unknown;
for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (attempt === opts.maxAttempts) break;
if (options?.shouldRetry && !options.shouldRetry(error, attempt)) {
break;
}
const customDelay = options?.getDelayMs?.(error, attempt);
const delay = customDelay ?? Math.min(
opts.initialDelayMs * opts.backoffMultiplier ** (attempt - 1),
opts.maxDelayMs,
);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
throw lastError;
}