Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9.0 KiB
9.0 KiB
@suaveplan/retry - Retry strategies with exponential/linear/constant backoff, jitter, circuit breaker with half-open probing, sleep and timeout helpers
Summary
Retry strategies and circuit-breaker for async operations. The package provides constant, linear, and exponential backoff with four jitter modes (full, equal, decorrelated, none), a sleep helper with AbortSignal support, a per-attempt withTimeout wrapper, and a three-state circuit breaker (closed → open → half-open) with event emission and configurable failure/success thresholds. All entry points accept an injectable Clock and AbortSignal so they integrate cleanly with test harnesses and request cancellation.
Documentation tree
- circuit-breaker — (no submodules)
- circuit-breaker — (no submodules)
- errors — (no submodules)
- retry-error — (no submodules)
- otel — (no submodules)
- retry-otel — (no submodules)
- retry — (no submodules)
- retry — (no submodules)
- constant — (no submodules)
- constant — (no submodules)
- exponential — (no submodules)
- exponential — (no submodules)
- linear — (no submodules)
- linear — (no submodules)
Install
bun add @suaveplan/retry
Quick Start
import {
withRetry,
createExponentialBackoff,
CircuitBreaker,
} from "@suaveplan/retry";
// Retry with exponential backoff and full jitter — up to 5 attempts.
const result = await withRetry(
async (signal) => {
const res = await fetch("https://api.example.com/data", { signal });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
},
{
maxAttempts: 5,
delay: createExponentialBackoff({ initial: 100, max: 5000, jitter: "full" }),
}
);
// Wrap a sensitive downstream call in a circuit breaker.
const breaker = new CircuitBreaker({
failureThreshold: 3,
successThreshold: 2,
timeout: 10_000,
});
breaker.on("open", ({ openedAt }) => console.warn("Circuit opened at", openedAt));
const value = await breaker.call(async (signal) => {
return fetchDownstream(signal);
});
Modules
| Module | Path |
|---|---|
retry — core loop, retry, withRetry, sleep, withTimeout, createDelayFn |
src/retry/retry.md |
constant — createConstantBackoff |
src/strategies/constant/constant.md |
linear — createLinearBackoff |
src/strategies/linear/linear.md |
exponential — createExponentialBackoff, applyJitter |
src/strategies/exponential/exponential.md |
circuit-breaker — CircuitBreaker class, CircuitBreakerConfig, event map |
src/circuit-breaker/circuit-breaker.md |
retry-error — RetryExhaustedError, RetryAbortedError, AttemptTimeoutError, CircuitOpenError |
src/errors/retry-error.md |
retry-otel — OpenTelemetry span/event helpers |
src/otel/retry-otel.md |