method TaskClass.prototype.retry
Private
TaskClass.prototype.retry(
times?: number,
): 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

Parameters

optional
times: number = 1
optional
options: RetryDelay | RetryOptions

Return Type

Usage

import { TaskClass } from "lib/task/task.ts";