/** * @module @dotdo/postgres-shared/circuit-breaker-unified * * Unified Circuit Breaker API * * This module provides a unified circuit breaker interface that consolidates * features from multiple implementations into a single, flexible API. It supports * both single-instance mode (for services like CDC) and multi-instance mode * (for DO routing scenarios). * * ## When to Use This vs Base CircuitBreaker * * Use **UnifiedCircuitBreaker** when you need: * - Single-instance mode (no instance IDs) * - Built-in retry functionality with executeWithRetry() * - Active recovery strategy (timer-based state transitions) * - A simpler API that adapts to your use case * * Use **CircuitBreaker** (base) when you need: * - Direct DO stub wrapping with DOCircuitBreakerWrapper * - More explicit multi-instance control * - Direct compatibility with existing code * * ## Features * * - **Dual Mode**: Single-instance (like CDC) or multi-instance (like DO routing) * - **Recovery Strategies**: Passive (on getState check) or active (timer-based) * - **Retry Support**: Built-in executeWithRetry() with exponential backoff * - **Cleanup**: destroy() method for proper resource cleanup * - **Full Compatibility**: Wraps the base CircuitBreaker for consistency * * ## Quick Start * * @example Single-instance mode (for CDC, single service) * ```typescript * import { createUnifiedCircuitBreaker, CircuitBreakerError } from '@dotdo/postgres-shared' * * const cb = createUnifiedCircuitBreaker({ * mode: 'single', * failureThreshold: 5, * resetTimeoutMs: 10000, * recoveryStrategy: 'active', // Uses timers for automatic recovery * }) * * try { * // No instance ID needed in single mode * const result = await cb.execute(async () => { * return await fetchFromCDCService() * }) * } catch (error) { * if (error instanceof CircuitBreakerError) { * console.log(`Circuit open, retry after ${error.retryAfterMs}ms`) * } * } * * // Cleanup when done * cb.destroy() * ``` * * @example Multi-instance mode (for DO routing) * ```typescript * import { createUnifiedCircuitBreaker } from '@dotdo/postgres-shared' * * const cb = createUnifiedCircuitBreaker({ * mode: 'multi', * failureThreshold: 3, * resetTimeoutMs: 30000, * enableExponentialBackoff: true, * }) * * // Track each tenant/DO instance separately * const result = await cb.execute('tenant-123', async () => { * return await doStub.fetch(request) * }) * * // Check state per instance * console.log('Tenant 123 state:', cb.getState('tenant-123')) * console.log('Tenant 456 state:', cb.getState('tenant-456')) * ``` * * @example With retry support * ```typescript * const cb = createUnifiedCircuitBreaker({ mode: 'single' }) * * // Automatically retries with exponential backoff * const result = await cb.executeWithRetry( * async () => unreliableOperation(), * { maxRetries: 3, delayMs: 1000 } * ) * ``` * * @see CircuitBreaker for the base multi-instance implementation * @see DOCircuitBreakerWrapper for wrapping DO stubs directly */ import { CircuitBreaker, CircuitBreakerConfig, CircuitBreakerStats, CircuitBreakerEvent, CircuitBreakerMetricsCollector, CircuitBreakerMetricsSummary, DefaultMetricsCollector, DOCircuitBreakerWrapper, DOCircuitBreakerConfig, DOStub } from './circuit-breaker.js'; import { CircuitOpenError } from './errors.js'; export type { CircuitBreakerEvent, CircuitBreakerMetricsCollector, CircuitBreakerMetricsSummary }; /** * Circuit state type (string literal union for better TypeScript inference) */ export type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN'; /** * Unified circuit breaker configuration */ export interface UnifiedCircuitBreakerConfig extends Omit { /** Operating mode: 'single' for single-instance, 'multi' for multi-instance (default: 'multi') */ mode?: 'single' | 'multi'; /** Recovery strategy: 'passive' checks on getState, 'active' uses timers (default: 'passive') */ recoveryStrategy?: 'passive' | 'active'; /** Event handler for circuit breaker events */ onEvent?: (event: CircuitBreakerEvent) => void; } /** * Unified statistics interface combining all implementations */ export interface UnifiedCircuitBreakerStats extends CircuitBreakerStats { /** Number of successes in half-open state (from CDC) */ halfOpenSuccesses: number; /** Number of times circuit has opened (from CDC) */ openCount: number; } /** * Unified Circuit Breaker class * * Wraps the base CircuitBreaker to provide a unified API that supports * both single-instance and multi-instance modes. */ export declare class UnifiedCircuitBreaker { private readonly cb; private readonly mode; private readonly recoveryStrategy; private readonly _config; private activeRecoveryTimers; private openCounts; private static readonly DEFAULT_INSTANCE; constructor(config?: UnifiedCircuitBreakerConfig); /** * Schedule active recovery transition from OPEN to HALF_OPEN */ private scheduleActiveRecovery; /** * Clear active recovery timer for an instance */ private clearRecoveryTimer; /** * Get the instance ID based on mode */ private resolveInstanceId; /** * Get the current state of the circuit * * @param instanceId - Instance ID (only used in multi mode) */ getState(instanceId?: string): CircuitState; /** * Check if a request is allowed to proceed * * @param instanceId - Instance ID (only used in multi mode) */ isAllowed(instanceId?: string): boolean; /** * Check if a request can be executed (alias for isAllowed) * * @param instanceId - Instance ID (only used in multi mode) */ canExecute(instanceId?: string): boolean; /** * Record a successful operation * * @param instanceId - Instance ID (only used in multi mode) */ recordSuccess(instanceId?: string): void; /** * Record a failed operation * * @param instanceId - Instance ID (only used in multi mode) */ recordFailure(instanceId?: string): void; /** * Execute a function with circuit breaker protection * * In single mode: execute(fn) * In multi mode: execute(instanceId, fn) or execute(fn) with default instance */ execute(fnOrInstanceId: string | (() => Promise), fn?: () => Promise): Promise; /** * Execute a function with circuit breaker protection and automatic retry * * In single mode: executeWithRetry(fn, options) * In multi mode: executeWithRetry(instanceId, fn, options) or executeWithRetry(fn, options) */ executeWithRetry(fnOrInstanceId: string | (() => Promise), fnOrOptions?: (() => Promise) | { maxRetries?: number; delayMs?: number; }, options?: { maxRetries?: number; delayMs?: number; }): Promise; /** * Get statistics for an instance or the default instance * * @param instanceId - Instance ID (only used in multi mode) */ getStats(instanceId?: string): UnifiedCircuitBreakerStats; /** * Get statistics for all tracked instances */ getAllStats(): Map; /** * Get the current configuration */ getConfig(): Required>; /** * Manually reset the circuit for an instance * * @param instanceId - Instance ID (only used in multi mode) */ reset(instanceId?: string): void; /** * Manually force a circuit to open * * @param instanceId - Instance ID (only used in multi mode) */ forceOpen(instanceId?: string): void; /** * Force the circuit to a specific state * * @param state - The state to force * @param instanceId - Instance ID (only used in multi mode) */ forceState(state: CircuitState, instanceId?: string): void; /** * Remove tracking for an instance * * @param instanceId - Instance ID to remove */ remove(instanceId: string): boolean; /** * Clear all tracked instances */ clear(): void; /** * Cleanup all resources (timers, etc.) * Call this when the circuit breaker is no longer needed. * Note: This only clears timers, not the circuit state. */ destroy(): void; } /** * Create a unified circuit breaker instance * * @example * ```typescript * // Single-instance mode (like CDC) * const cb = createUnifiedCircuitBreaker({ mode: 'single' }) * * // Multi-instance mode (like DO routing) * const cb = createUnifiedCircuitBreaker({ mode: 'multi' }) * ``` */ export declare function createUnifiedCircuitBreaker(config?: UnifiedCircuitBreakerConfig): UnifiedCircuitBreaker; export { CircuitOpenError as CircuitBreakerError }; export { CircuitBreaker, DefaultMetricsCollector, DOCircuitBreakerWrapper, CircuitOpenError }; export type { CircuitBreakerConfig, CircuitBreakerStats, DOCircuitBreakerConfig, DOStub }; //# sourceMappingURL=circuit-breaker-unified.d.ts.map