UNPKG

@zerothrow/resilience

Version:

Production-grade resilience patterns for ZeroThrow

164 lines (154 loc) 6.02 kB
import { Result } from '@zerothrow/core'; interface Policy$1 { execute<T>(operation: () => Promise<T>): Promise<Result<T, Error>>; } interface RetryPolicy$1 extends Policy$1 { onRetry(callback: (attempt: number, error: unknown, delay: number) => void): RetryPolicy$1; } interface CircuitBreakerPolicy$1 extends Policy$1 { onCircuitStateChange(callback: (state: 'open' | 'closed' | 'half-open') => void): CircuitBreakerPolicy$1; } type TimeoutPolicy$1 = Policy$1; type AnyPolicy = RetryPolicy$1 | CircuitBreakerPolicy$1 | TimeoutPolicy$1 | Policy$1; interface RetryOptions { backoff?: 'constant' | 'linear' | 'exponential'; delay?: number; maxDelay?: number; handle?: (error: Error) => boolean; } interface CircuitOptions { threshold: number; duration: number; onOpen?: () => void; onClose?: () => void; } interface TimeoutOptions { timeout: number; } interface PolicyError extends Error { type: PolicyErrorType; policyName: string; context?: unknown; } type PolicyErrorType = 'retry-exhausted' | 'circuit-open' | 'timeout'; declare class RetryExhaustedError extends Error implements PolicyError { readonly policyName: string; readonly attempts: number; readonly lastError: Error; readonly context?: unknown | undefined; readonly type: "retry-exhausted"; constructor(policyName: string, attempts: number, lastError: Error, context?: unknown | undefined); } declare class CircuitOpenError extends Error implements PolicyError { readonly policyName: string; readonly openedAt: Date; readonly failureCount: number; readonly context?: unknown | undefined; readonly type: "circuit-open"; constructor(policyName: string, openedAt: Date, failureCount: number, context?: unknown | undefined); } declare class TimeoutError extends Error implements PolicyError { readonly policyName: string; readonly timeout: number; readonly elapsed: number; readonly context?: unknown | undefined; readonly type: "timeout"; constructor(policyName: string, timeout: number, elapsed: number, context?: unknown | undefined); } interface Clock { now(): Date; sleep(ms: number): Promise<void>; } declare class SystemClock implements Clock { now(): Date; sleep(ms: number): Promise<void>; } declare class TestClock implements Clock { private currentTime; private sleepers; now(): Date; sleep(ms: number): Promise<void>; advance(ms: number): void; setTime(time: Date | number): void; } declare abstract class BasePolicy implements Policy$1 { protected readonly name: string; protected readonly clock: Clock; constructor(name: string, clock?: Clock); abstract execute<T>(operation: () => Promise<T>): Promise<Result<T, Error>>; protected runOperation<T>(operation: () => Promise<T>): Promise<Result<T, Error>>; } declare class RetryPolicy extends BasePolicy implements RetryPolicy$1 { private readonly count; private readonly options; private retryCallback?; constructor(count: number, options?: RetryOptions, clock?: Clock); execute<T>(operation: () => Promise<T>): Promise<Result<T, Error>>; onRetry(callback: (attempt: number, error: unknown, delay: number) => void): RetryPolicy$1; private calculateDelay; } type CircuitState = 'closed' | 'open' | 'half-open'; declare class CircuitBreakerPolicy extends BasePolicy implements CircuitBreakerPolicy$1 { private readonly options; private state; private failures; private lastFailureTime?; private nextAllowedTime?; private stateChangeCallback?; constructor(options: CircuitOptions, clock?: Clock); execute<T>(operation: () => Promise<T>): Promise<Result<T, Error>>; private onSuccess; private onFailure; private open; private reset; private setState; onCircuitStateChange(callback: (state: CircuitState) => void): CircuitBreakerPolicy$1; } declare class TimeoutPolicy extends BasePolicy { private readonly options; constructor(options: TimeoutOptions, clock?: Clock); execute<T>(operation: () => Promise<T>): Promise<Result<T, Error>>; } /** * Wraps one policy with another, creating a composed policy. * The outer policy executes first and passes its operation to the inner policy. * * Example: Policy.wrap(retry, timeout) creates a policy that retries with timeouts */ declare function wrap(outer: Policy$1, inner: Policy$1): Policy$1; /** * Composes multiple policies from left to right. * The leftmost policy is the outermost wrapper. * * Example: compose(retry, circuit, timeout) * Results in: retry wraps (circuit wraps (timeout wraps operation)) */ declare function compose(...policies: Policy$1[]): Policy$1; /** * Main factory for creating resilience policies */ declare const Policy: { /** * Creates a retry policy */ readonly retry: (count: number, options?: RetryOptions, clock?: Clock) => RetryPolicy; /** * Creates a circuit breaker policy */ readonly circuitBreaker: (options: CircuitOptions, clock?: Clock) => CircuitBreakerPolicy; /** * Creates a timeout policy */ readonly timeout: (options: TimeoutOptions | number, clock?: Clock) => TimeoutPolicy; /** * Wraps one policy with another * The outer policy executes first */ readonly wrap: typeof wrap; /** * Composes multiple policies from left to right * The leftmost policy is the outermost wrapper */ readonly compose: typeof compose; }; export { type AnyPolicy, CircuitBreakerPolicy, type CircuitBreakerPolicy$1 as CircuitBreakerPolicyInterface, CircuitOpenError, type CircuitOptions, type Clock, type Policy$1 as Policy, type PolicyError, type PolicyErrorType, Policy as PolicyFactory, RetryExhaustedError, type RetryOptions, RetryPolicy, type RetryPolicy$1 as RetryPolicyInterface, SystemClock, TestClock, TimeoutError, type TimeoutOptions, TimeoutPolicy, type TimeoutPolicy$1 as TimeoutPolicyInterface, compose, wrap };