70f1c47a28
* Stop using command-based logs for warnings and errors Co-authored-by: Cursor <cursoragent@cursor.com> * revert * tweak * de-noise * Remove redundant ts() timestamp prefix from log calls * Restore timestamped logging and refine debug output routing. Bring back timestamp prefixes for standard logs and make log.debug emit via core.debug when runner debug is enabled, while still surfacing debug lines for --debug runs. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com> Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
47 lines
1.3 KiB
TypeScript
47 lines
1.3 KiB
TypeScript
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.info(`» ${label} failed (attempt ${attempt}/${maxAttempts}), retrying in ${delay}ms...`);
|
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
}
|
|
}
|
|
|
|
throw lastError;
|
|
}
|