TaskClass.prototype.retry(times?: number,options?: RetryDelay | RetryOptions): TaskClass<T, E>
Re-runs until success, spawning a fresh TaskClass#restart execution per attempt —
the first attempt included, so a Task that already ran and failed retries cleanly. Gives up
after times retries (initial + times executions) and rejects with the last reason.
Failure-blind by design: transient bugs (a socket reset surfacing as a raw error before its
mapErr) are exactly what call sites retry, so every rejection counts as an attempt.
An attempt that fails is then abandoned: its AbortSignal fires so an executor that
subscribed to something can unsubscribe, rather than leaving a listener behind per attempt.
The attempt has already settled, so this changes no outcome and its reason never reaches
the caller — the failure they see is their own. Recipes take no signal and are untouched.
The second argument is the wait between attempts — a number, or a function of the attempt
just finished for backoff — or the full { delayMs, timeoutMs } bag. timeoutMs bounds
each attempt individually: the deadline abandons it (its signal fires, so cancellation-aware
work stops) and it counts as a failure like any other. A pending wait is abortable, so
shutdown() during one settles immediately rather than outliving the Task.
import { getChangedFilePathsInGitSince } from '../utils/get-changed-file-paths-in-git-since.ts'; // Defined, not invoked: the scan spawns real git subprocesses when awaited. function resilientScan(root: string, ref: string) { return getChangedFilePathsInGitSince(root, ref).retry(); // survives index.lock contention } let attempts = 0; const flakyUpload = Task(() => (++attempts < 3 ? Promise.reject(new Error('flaky')) : 'ok')); await flakyUpload.retry(4); // 'ok' — succeeded on the 3rd of up to 5 fresh executions attempts = 0; await flakyUpload.retry(4, 1); // the same, waiting 1ms between attempts attempts = 0; await flakyUpload.retry(4, (attempt) => attempt); // backoff: 1ms, then 2ms attempts = 0; await flakyUpload.retry(4, { delayMs: 1, timeoutMs: 5_000 }); // and a per-attempt deadline
options: RetryDelay | RetryOptions