Add retrying. Improve diff format

This commit is contained in:
Colin McDonnell
2025-12-22 15:53:11 -08:00
parent 615a3bc8e1
commit c518e8b6fd
7 changed files with 213 additions and 39 deletions
+47
View File
@@ -0,0 +1,47 @@
import { log } from "./cli.ts";
export type RetryOptions = {
maxAttempts?: number;
delayMs?: number;
shouldRetry?: (error: unknown) => boolean;
label?: string;
};
const defaultShouldRetry = (error: unknown): boolean => {
if (!(error instanceof Error)) return false;
// retry on transient network errors
return (
error.name === "AbortError" ||
error.message.includes("fetch failed") ||
error.message.includes("ECONNRESET") ||
error.message.includes("ETIMEDOUT")
);
};
export async function retry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {
const maxAttempts = options.maxAttempts ?? 3;
const delayMs = options.delayMs ?? 1000;
const shouldRetry = options.shouldRetry ?? defaultShouldRetry;
const label = options.label ?? "operation";
let lastError: unknown;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (attempt === maxAttempts || !shouldRetry(error)) {
throw error;
}
const delay = delayMs * attempt;
log.warning(`» ${label} failed (attempt ${attempt}/${maxAttempts}), retrying in ${delay}ms...`);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
throw lastError;
}