Files
cloudflare--workers-sdk/packages/workers-utils/src/retry.ts
T
wehub-resource-sync 70bf21e064
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:11 +08:00

46 lines
1.0 KiB
TypeScript

import { setTimeout } from "node:timers/promises";
import { APIError } from "./parse";
import type { Logger } from "./logger";
const MAX_ATTEMPTS = 3;
export async function retryOnAPIFailure<T>(
action: () => T | Promise<T>,
logger: Logger,
backoff = 0,
attempts = MAX_ATTEMPTS,
abortSignal?: AbortSignal
): Promise<T> {
try {
return await action();
} catch (err) {
if (err instanceof APIError) {
if (!err.isRetryable()) {
throw err;
}
} else if (err instanceof DOMException && err.name === "TimeoutError") {
// Per-request timeouts (from AbortSignal.timeout()) are transient
// and should be retried, but user-initiated aborts (AbortError)
// should not.
} else if (!(err instanceof TypeError)) {
throw err;
}
logger.debug(`Retrying API call after error...`);
logger.debug(err);
if (attempts <= 1) {
throw err;
}
await setTimeout(backoff, undefined, { signal: abortSignal });
return retryOnAPIFailure(
action,
logger,
backoff + 1000,
attempts - 1,
abortSignal
);
}
}