.retry(count, options?)
Retries a failed task up to count times. Optionally applies a delay between attempts with exponential backoff.
factor: 2 and delay: 1000, the delays between retries are: 1000 ms, 2000 ms, 4000 ms.
.timeout(ms, onTimeout)
Fails with the value returned by onTimeout if the task has not completed within ms milliseconds.
.circuitBreaker({ threshold, resetTimeout })
Protects downstream services by opening the circuit after threshold consecutive failures. While the circuit is open, the Task fails immediately with the string 'CIRCUIT_OPEN' without attempting execution.
After resetTimeout milliseconds, the circuit enters a half-open state and allows one attempt through. If it succeeds, the circuit closes. If it fails, it reopens.
The circuit breaker state is held on the Task instance. Create one shared instance and reuse it across concurrent calls for the breaker to function correctly.
.throttle(concurrency)
Limits the number of simultaneous executions of the Task. Excess calls queue and wait for a slot to open.
This is useful when calling a rate-limited API from code that launches tasks in parallel:
Like
.circuitBreaker(), the throttle state is held on the Task instance. Reuse the same instance for the limit to take effect across concurrent callers..delay(ms)
Adds a fixed delay before the Task begins executing.
.withSignal(signal)
Binds an AbortSignal to the Task. If the signal is already aborted when .execute() is called, or fires while the Task is running, the Task fails immediately with the abort reason.
.execute() as a shorthand:
Combining resilience operators
Resilience operators compose naturally. A realistic pattern for a production API call:- The fetch is retried up to 3 times with backoff on failure.
- The entire retry sequence must complete within 10 seconds.
- If 5 consecutive attempts fail, the circuit opens and subsequent calls return immediately.
- If the circuit is open (or all retries are exhausted), the fallback Task runs instead.
Caching operators
.once()
Executes the Task exactly once and caches the Result for the lifetime of the instance. Every subsequent call to .execute() returns the cached result without re-running the underlying logic.
Best suited for one-time initialization work:
.memoize({ ttl?, cacheErr? })
In-memory memoization with an optional time-to-live. While the cache is valid, .execute() returns the stored Result without re-running the Task.
cacheErr: true caches error results too, which prevents hammering a failing service:
.cache(key, store, { ttl? })
Delegates caching to an external store via the TaskCache interface. Useful for sharing cached data across process restarts or multiple instances.
Map satisfies TaskCache:
TaskCache against Redis, IndexedDB, or any other store: