@revealui/resilience 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -260,6 +260,77 @@ declare function createResilientFunction<T>(fn: () => Promise<T>, options?: {
260
260
  };
261
261
  }): () => Promise<T>;
262
262
 
263
+ /**
264
+ * Circuit Breaker State Store — Pluggable backends for circuit breaker persistence.
265
+ *
266
+ * - InMemoryCircuitBreakerStore: Map-backed, single-instance (default)
267
+ * - PGliteCircuitBreakerStore: SQL-backed via PGlite, persistent across restarts
268
+ *
269
+ * Stores only the durable state needed for recovery: state, counters, timestamps.
270
+ * Timers and callbacks remain in-memory on the CircuitBreaker instance.
271
+ */
272
+
273
+ interface CircuitBreakerSnapshot {
274
+ state: CircuitState;
275
+ failureCount: number;
276
+ successCount: number;
277
+ consecutiveFailures: number;
278
+ consecutiveSuccesses: number;
279
+ lastFailureAt: number;
280
+ lastSuccessAt: number;
281
+ stateChangedAt: number;
282
+ }
283
+ /**
284
+ * Pluggable storage backend for circuit breaker state.
285
+ * Each service gets its own named breaker.
286
+ */
287
+ interface CircuitBreakerStore {
288
+ /** Load the state for a named service, or null if no state exists. */
289
+ load(name: string): Promise<CircuitBreakerSnapshot | null>;
290
+ /** Persist a snapshot for a named service. */
291
+ save(name: string, snapshot: CircuitBreakerSnapshot): Promise<void>;
292
+ /** Remove state for a named service. Returns true if it existed. */
293
+ remove(name: string): Promise<boolean>;
294
+ /** Clear all circuit breaker state. */
295
+ clear(): Promise<void>;
296
+ /** Release any resources. */
297
+ close(): Promise<void>;
298
+ }
299
+ declare class InMemoryCircuitBreakerStore implements CircuitBreakerStore {
300
+ private state;
301
+ load(name: string): Promise<CircuitBreakerSnapshot | null>;
302
+ save(name: string, snapshot: CircuitBreakerSnapshot): Promise<void>;
303
+ remove(name: string): Promise<boolean>;
304
+ clear(): Promise<void>;
305
+ close(): Promise<void>;
306
+ }
307
+ /** Minimal PGlite interface — avoids importing the full @electric-sql/pglite package. */
308
+ interface PGliteInstance {
309
+ exec(query: string): Promise<unknown>;
310
+ query<T = Record<string, unknown>>(query: string, params?: unknown[]): Promise<{
311
+ rows: T[];
312
+ }>;
313
+ close(): Promise<void>;
314
+ }
315
+ interface PGliteCircuitBreakerStoreOptions {
316
+ /** PGlite instance (caller owns lifecycle unless closeOnDestroy is true). */
317
+ db: PGliteInstance;
318
+ /** Close the PGlite instance when close() is called (default: false). */
319
+ closeOnDestroy?: boolean;
320
+ }
321
+ declare class PGliteCircuitBreakerStore implements CircuitBreakerStore {
322
+ private db;
323
+ private ready;
324
+ private closeOnDestroy;
325
+ constructor(options: PGliteCircuitBreakerStoreOptions);
326
+ private init;
327
+ load(name: string): Promise<CircuitBreakerSnapshot | null>;
328
+ save(name: string, snapshot: CircuitBreakerSnapshot): Promise<void>;
329
+ remove(name: string): Promise<boolean>;
330
+ clear(): Promise<void>;
331
+ close(): Promise<void>;
332
+ }
333
+
263
334
  /**
264
335
  * Internal logger for @revealui/resilience.
265
336
  *
@@ -474,4 +545,4 @@ declare class GlobalRetryConfig {
474
545
  }
475
546
  declare const globalRetryConfig: GlobalRetryConfig;
476
547
 
477
- export { AdaptiveCircuitBreaker, Bulkhead, CircuitBreak, CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, CircuitBreakerRegistry, type CircuitBreakerStats, type CircuitState, ExponentialBackoff, type HttpError, type ResilienceLogger, ResilientOperation, type RetryConfig, type RetryOptions, RetryPolicies, RetryPolicyBuilder, Retryable, RetryableOperation, calculateDelay, circuitBreakerRegistry, configureResilienceLogger, createCircuitBreakerMiddleware, createResilientFunction, createRetryMiddleware, fetchWithCircuitBreaker, fetchWithRetry, getResilienceLogger, globalRetryConfig, retry, retryBatch, retryIf, retryUntil, retryWithFallback, sleep, withCircuitBreaker };
548
+ export { AdaptiveCircuitBreaker, Bulkhead, CircuitBreak, CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, CircuitBreakerRegistry, type CircuitBreakerSnapshot, type CircuitBreakerStats, type CircuitBreakerStore, type CircuitState, ExponentialBackoff, type HttpError, InMemoryCircuitBreakerStore, PGliteCircuitBreakerStore, type ResilienceLogger, ResilientOperation, type RetryConfig, type RetryOptions, RetryPolicies, RetryPolicyBuilder, Retryable, RetryableOperation, calculateDelay, circuitBreakerRegistry, configureResilienceLogger, createCircuitBreakerMiddleware, createResilientFunction, createRetryMiddleware, fetchWithCircuitBreaker, fetchWithRetry, getResilienceLogger, globalRetryConfig, retry, retryBatch, retryIf, retryUntil, retryWithFallback, sleep, withCircuitBreaker };
package/dist/index.js CHANGED
@@ -480,6 +480,118 @@ function createResilientFunction(fn, options = {}) {
480
480
  return () => operation.execute();
481
481
  }
482
482
 
483
+ // src/circuit-breaker-store.ts
484
+ var InMemoryCircuitBreakerStore = class {
485
+ state = /* @__PURE__ */ new Map();
486
+ async load(name) {
487
+ const snapshot = this.state.get(name);
488
+ return snapshot ? { ...snapshot } : null;
489
+ }
490
+ async save(name, snapshot) {
491
+ this.state.set(name, { ...snapshot });
492
+ }
493
+ async remove(name) {
494
+ return this.state.delete(name);
495
+ }
496
+ async clear() {
497
+ this.state.clear();
498
+ }
499
+ async close() {
500
+ this.state.clear();
501
+ }
502
+ };
503
+ var CREATE_CB_TABLE_SQL = `
504
+ CREATE TABLE IF NOT EXISTS _circuit_breaker_state (
505
+ name TEXT PRIMARY KEY,
506
+ state TEXT NOT NULL DEFAULT 'closed',
507
+ failure_count INTEGER NOT NULL DEFAULT 0,
508
+ success_count INTEGER NOT NULL DEFAULT 0,
509
+ consecutive_failures INTEGER NOT NULL DEFAULT 0,
510
+ consecutive_successes INTEGER NOT NULL DEFAULT 0,
511
+ last_failure_at BIGINT NOT NULL DEFAULT 0,
512
+ last_success_at BIGINT NOT NULL DEFAULT 0,
513
+ state_changed_at BIGINT NOT NULL DEFAULT 0
514
+ );
515
+ `;
516
+ var PGliteCircuitBreakerStore = class {
517
+ db;
518
+ ready;
519
+ closeOnDestroy;
520
+ constructor(options) {
521
+ this.db = options.db;
522
+ this.closeOnDestroy = options.closeOnDestroy ?? false;
523
+ this.ready = this.init();
524
+ }
525
+ async init() {
526
+ await this.db.exec(CREATE_CB_TABLE_SQL);
527
+ }
528
+ async load(name) {
529
+ await this.ready;
530
+ const result = await this.db.query(
531
+ "SELECT state, failure_count, success_count, consecutive_failures, consecutive_successes, last_failure_at, last_success_at, state_changed_at FROM _circuit_breaker_state WHERE name = $1",
532
+ [name]
533
+ );
534
+ const row = result.rows[0];
535
+ if (!row) return null;
536
+ return {
537
+ state: row.state,
538
+ failureCount: row.failure_count,
539
+ successCount: row.success_count,
540
+ consecutiveFailures: row.consecutive_failures,
541
+ consecutiveSuccesses: row.consecutive_successes,
542
+ lastFailureAt: Number(row.last_failure_at),
543
+ lastSuccessAt: Number(row.last_success_at),
544
+ stateChangedAt: Number(row.state_changed_at)
545
+ };
546
+ }
547
+ async save(name, snapshot) {
548
+ await this.ready;
549
+ await this.db.query(
550
+ `INSERT INTO _circuit_breaker_state
551
+ (name, state, failure_count, success_count, consecutive_failures, consecutive_successes, last_failure_at, last_success_at, state_changed_at)
552
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
553
+ ON CONFLICT (name) DO UPDATE SET
554
+ state = EXCLUDED.state,
555
+ failure_count = EXCLUDED.failure_count,
556
+ success_count = EXCLUDED.success_count,
557
+ consecutive_failures = EXCLUDED.consecutive_failures,
558
+ consecutive_successes = EXCLUDED.consecutive_successes,
559
+ last_failure_at = EXCLUDED.last_failure_at,
560
+ last_success_at = EXCLUDED.last_success_at,
561
+ state_changed_at = EXCLUDED.state_changed_at`,
562
+ [
563
+ name,
564
+ snapshot.state,
565
+ snapshot.failureCount,
566
+ snapshot.successCount,
567
+ snapshot.consecutiveFailures,
568
+ snapshot.consecutiveSuccesses,
569
+ snapshot.lastFailureAt,
570
+ snapshot.lastSuccessAt,
571
+ snapshot.stateChangedAt
572
+ ]
573
+ );
574
+ }
575
+ async remove(name) {
576
+ await this.ready;
577
+ const result = await this.db.query(
578
+ `WITH deleted AS (DELETE FROM _circuit_breaker_state WHERE name = $1 RETURNING 1)
579
+ SELECT count(*)::text AS count FROM deleted`,
580
+ [name]
581
+ );
582
+ return Number.parseInt(result.rows[0]?.count ?? "0", 10) > 0;
583
+ }
584
+ async clear() {
585
+ await this.ready;
586
+ await this.db.exec("DELETE FROM _circuit_breaker_state");
587
+ }
588
+ async close() {
589
+ if (this.closeOnDestroy) {
590
+ await this.db.close();
591
+ }
592
+ }
593
+ };
594
+
483
595
  // src/retry.ts
484
596
  import { randomInt } from "crypto";
485
597
  var DEFAULT_CONFIG2 = {
@@ -889,6 +1001,8 @@ export {
889
1001
  CircuitBreakerOpenError,
890
1002
  CircuitBreakerRegistry,
891
1003
  ExponentialBackoff,
1004
+ InMemoryCircuitBreakerStore,
1005
+ PGliteCircuitBreakerStore,
892
1006
  ResilientOperation,
893
1007
  RetryPolicies,
894
1008
  RetryPolicyBuilder,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger.ts","../src/circuit-breaker.ts","../src/retry.ts"],"sourcesContent":["/**\n * Internal logger for @revealui/resilience.\n *\n * Defaults to `console`. Consumers should call `configureResilienceLogger()`\n * to supply a structured logger (e.g. from `@revealui/utils/logger`).\n */\n\nexport interface ResilienceLogger {\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n debug(message: string, ...args: unknown[]): void;\n}\n\nlet resilienceLogger: ResilienceLogger = console;\n\n/**\n * Replace the default console logger with a structured logger.\n */\nexport function configureResilienceLogger(logger: ResilienceLogger): void {\n resilienceLogger = logger;\n}\n\n/**\n * Get the current resilience logger instance.\n */\nexport function getResilienceLogger(): ResilienceLogger {\n return resilienceLogger;\n}\n","/**\n * Circuit Breaker Pattern\n *\n * Prevents cascading failures by stopping requests to failing services\n */\n\nimport { getResilienceLogger } from './logger.js';\nimport type { HttpError } from './retry.js';\n\nexport type CircuitState = 'closed' | 'open' | 'half-open';\n\nexport interface CircuitBreakerConfig {\n failureThreshold?: number;\n successThreshold?: number;\n timeout?: number;\n resetTimeout?: number;\n volumeThreshold?: number;\n errorFilter?: (error: Error) => boolean;\n onStateChange?: (state: CircuitState) => void;\n onTrip?: () => void;\n onReset?: () => void;\n}\n\nexport interface CircuitBreakerStats {\n [key: string]: unknown;\n state: CircuitState;\n failures: number;\n successes: number;\n consecutiveFailures: number;\n consecutiveSuccesses: number;\n totalCalls: number;\n totalFailures: number;\n totalSuccesses: number;\n lastFailureTime?: number;\n lastSuccessTime?: number;\n stateChangedAt: number;\n}\n\nconst DEFAULT_CONFIG: Required<CircuitBreakerConfig> = {\n failureThreshold: 5,\n successThreshold: 2,\n timeout: 60000,\n resetTimeout: 30000,\n volumeThreshold: 10,\n errorFilter: () => true,\n onStateChange: () => {\n // No-op default — consumers override via config\n },\n onTrip: () => {\n // No-op default — consumers override via config\n },\n onReset: () => {\n // No-op default — consumers override via config\n },\n};\n\n/**\n * Circuit Breaker implementation\n */\nexport class CircuitBreaker {\n private state: CircuitState = 'closed';\n private failures: number = 0;\n private successes: number = 0;\n private consecutiveFailures: number = 0;\n private consecutiveSuccesses: number = 0;\n private totalCalls: number = 0;\n private totalFailures: number = 0;\n private totalSuccesses: number = 0;\n private lastFailureTime?: number;\n private lastSuccessTime?: number;\n private stateChangedAt: number = Date.now();\n private resetTimer?: NodeJS.Timeout;\n protected config: Required<CircuitBreakerConfig>;\n\n constructor(config: CircuitBreakerConfig = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Execute function with circuit breaker\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check if circuit is open\n if (this.state === 'open') {\n // Check if reset timeout has passed\n if (Date.now() - this.stateChangedAt >= this.config.resetTimeout) {\n this.transitionTo('half-open');\n } else {\n throw new CircuitBreakerOpenError('Circuit breaker is open');\n }\n }\n\n this.totalCalls++;\n\n try {\n const result = await fn();\n this.onSuccess();\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n this.onFailure(err);\n throw error;\n }\n }\n\n /**\n * Handle successful execution\n */\n private onSuccess(): void {\n this.successes++;\n this.consecutiveSuccesses++;\n this.totalSuccesses++;\n this.consecutiveFailures = 0;\n this.lastSuccessTime = Date.now();\n\n if (this.state === 'half-open') {\n // Check if we can close the circuit\n if (this.consecutiveSuccesses >= this.config.successThreshold) {\n this.transitionTo('closed');\n }\n }\n\n // Reset failure count in closed state\n if (this.state === 'closed') {\n this.failures = 0;\n }\n }\n\n /**\n * Handle failed execution\n */\n private onFailure(error: Error): void {\n // Check if error should count\n if (!this.config.errorFilter(error)) {\n return;\n }\n\n this.failures++;\n this.consecutiveFailures++;\n this.totalFailures++;\n this.consecutiveSuccesses = 0;\n this.lastFailureTime = Date.now();\n\n if (this.state === 'half-open') {\n // Immediately open circuit on failure in half-open state\n this.transitionTo('open');\n } else if (this.state === 'closed') {\n // Check if we should open the circuit\n if (\n this.consecutiveFailures >= this.config.failureThreshold &&\n this.totalCalls >= this.config.volumeThreshold\n ) {\n this.transitionTo('open');\n }\n }\n }\n\n /**\n * Transition to new state\n */\n private transitionTo(newState: CircuitState): void {\n if (this.state === newState) return;\n\n const oldState = this.state;\n this.state = newState;\n this.stateChangedAt = Date.now();\n\n // Reset counters\n if (newState === 'half-open' || newState === 'closed') {\n this.consecutiveFailures = 0;\n this.consecutiveSuccesses = 0;\n }\n\n // Clear reset timer\n if (this.resetTimer) {\n clearTimeout(this.resetTimer);\n this.resetTimer = undefined;\n }\n\n // Set reset timer for open state\n if (newState === 'open') {\n this.resetTimer = setTimeout(() => {\n this.transitionTo('half-open');\n }, this.config.resetTimeout);\n\n this.config.onTrip();\n }\n\n // Circuit reset\n if (newState === 'closed' && oldState === 'half-open') {\n this.failures = 0;\n this.config.onReset();\n }\n\n this.config.onStateChange(newState);\n\n getResilienceLogger().info(\n `Circuit breaker state changed: ${oldState} -> ${newState}`,\n this.getStats(),\n );\n }\n\n /**\n * Get current state\n */\n getState(): CircuitState {\n return this.state;\n }\n\n /**\n * Get statistics\n */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n consecutiveFailures: this.consecutiveFailures,\n consecutiveSuccesses: this.consecutiveSuccesses,\n totalCalls: this.totalCalls,\n totalFailures: this.totalFailures,\n totalSuccesses: this.totalSuccesses,\n lastFailureTime: this.lastFailureTime,\n lastSuccessTime: this.lastSuccessTime,\n stateChangedAt: this.stateChangedAt,\n };\n }\n\n /**\n * Manually open circuit\n */\n trip(): void {\n this.transitionTo('open');\n }\n\n /**\n * Manually close circuit\n */\n reset(): void {\n this.failures = 0;\n this.successes = 0;\n this.consecutiveFailures = 0;\n this.consecutiveSuccesses = 0;\n this.transitionTo('closed');\n }\n\n /**\n * Force state to half-open\n */\n halfOpen(): void {\n this.transitionTo('half-open');\n }\n\n /**\n * Check if circuit is open\n */\n isOpen(): boolean {\n return this.state === 'open';\n }\n\n /**\n * Check if circuit is closed\n */\n isClosed(): boolean {\n return this.state === 'closed';\n }\n\n /**\n * Check if circuit is half-open\n */\n isHalfOpen(): boolean {\n return this.state === 'half-open';\n }\n\n /**\n * Get failure rate\n */\n getFailureRate(): number {\n if (this.totalCalls === 0) return 0;\n return this.totalFailures / this.totalCalls;\n }\n\n /**\n * Get success rate\n */\n getSuccessRate(): number {\n if (this.totalCalls === 0) return 0;\n return this.totalSuccesses / this.totalCalls;\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n if (this.resetTimer) {\n clearTimeout(this.resetTimer);\n }\n }\n}\n\n/**\n * Circuit breaker open error\n */\nexport class CircuitBreakerOpenError extends Error {\n constructor(message: string = 'Circuit breaker is open') {\n super(message);\n this.name = 'CircuitBreakerOpenError';\n }\n}\n\n/**\n * Circuit breaker registry\n */\nexport class CircuitBreakerRegistry {\n private breakers: Map<string, CircuitBreaker> = new Map();\n\n /**\n * Get or create circuit breaker\n */\n get(name: string, config?: CircuitBreakerConfig): CircuitBreaker {\n let breaker = this.breakers.get(name);\n\n if (!breaker) {\n breaker = new CircuitBreaker(config);\n this.breakers.set(name, breaker);\n }\n\n return breaker;\n }\n\n /**\n * Check if breaker exists\n */\n has(name: string): boolean {\n return this.breakers.has(name);\n }\n\n /**\n * Remove circuit breaker\n */\n remove(name: string): boolean {\n const breaker = this.breakers.get(name);\n if (breaker) {\n breaker.destroy();\n return this.breakers.delete(name);\n }\n return false;\n }\n\n /**\n * Get all breakers\n */\n getAll(): Map<string, CircuitBreaker> {\n return new Map(this.breakers);\n }\n\n /**\n * Get all statistics\n */\n getAllStats(): Record<string, CircuitBreakerStats> {\n const stats: Record<string, CircuitBreakerStats> = {};\n\n for (const [name, breaker] of this.breakers) {\n stats[name] = breaker.getStats();\n }\n\n return stats;\n }\n\n /**\n * Reset all breakers\n */\n resetAll(): void {\n for (const breaker of this.breakers.values()) {\n breaker.reset();\n }\n }\n\n /**\n * Clear all breakers\n */\n clear(): void {\n for (const breaker of this.breakers.values()) {\n breaker.destroy();\n }\n this.breakers.clear();\n }\n}\n\n/**\n * Global circuit breaker registry\n */\nexport const circuitBreakerRegistry = new CircuitBreakerRegistry();\n\n/**\n * Create circuit breaker decorator\n */\nexport function CircuitBreak(nameOrConfig: string | CircuitBreakerConfig = {}) {\n return (target: object, propertyKey: string, descriptor: PropertyDescriptor) => {\n const originalMethod = descriptor.value;\n const name =\n typeof nameOrConfig === 'string'\n ? nameOrConfig\n : `${(target as { constructor: { name: string } }).constructor.name}.${propertyKey}`;\n const config = typeof nameOrConfig === 'object' ? nameOrConfig : undefined;\n\n descriptor.value = async function (...args: unknown[]) {\n const breaker = circuitBreakerRegistry.get(name, config);\n return breaker.execute(() => originalMethod.apply(this, args));\n };\n\n return descriptor;\n };\n}\n\n/**\n * Execute with circuit breaker\n */\nexport async function withCircuitBreaker<T>(\n name: string,\n fn: () => Promise<T>,\n config?: CircuitBreakerConfig,\n): Promise<T> {\n const breaker = circuitBreakerRegistry.get(name, config);\n return breaker.execute(fn);\n}\n\n/**\n * Create circuit breaker middleware\n */\nexport function createCircuitBreakerMiddleware<TRequest = unknown, TResponse = unknown>(\n name: string,\n config?: CircuitBreakerConfig,\n) {\n const breaker = circuitBreakerRegistry.get(name, config);\n\n return async (_request: TRequest, next: () => Promise<TResponse>): Promise<TResponse> => {\n return breaker.execute(next);\n };\n}\n\n/**\n * Circuit breaker for fetch\n */\nexport async function fetchWithCircuitBreaker(\n name: string,\n url: string,\n init?: RequestInit,\n config?: CircuitBreakerConfig,\n): Promise<Response> {\n const breaker = circuitBreakerRegistry.get(name, config);\n\n return breaker.execute(async () => {\n const response = await fetch(url, init);\n\n // Treat 5xx errors as failures\n if (response.status >= 500) {\n const error = new Error(`HTTP ${response.status}: ${response.statusText}`) as HttpError;\n error.statusCode = response.status;\n throw error;\n }\n\n return response;\n });\n}\n\n/**\n * Adaptive circuit breaker with dynamic thresholds\n */\nexport class AdaptiveCircuitBreaker extends CircuitBreaker {\n private errorRateWindow: number[] = [];\n private windowSize: number = 100;\n private adaptiveThreshold: number;\n\n constructor(config: CircuitBreakerConfig = {}) {\n super(config);\n this.adaptiveThreshold = config.failureThreshold || 5;\n }\n\n /**\n * Execute with adaptive thresholds\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n try {\n const result = await super.execute(fn);\n this.recordSuccess();\n return result;\n } catch (error) {\n this.recordFailure();\n throw error;\n }\n }\n\n /**\n * Record success in window\n */\n private recordSuccess(): void {\n this.errorRateWindow.push(0);\n this.trimWindow();\n this.adjustThreshold();\n }\n\n /**\n * Record failure in window\n */\n private recordFailure(): void {\n this.errorRateWindow.push(1);\n this.trimWindow();\n this.adjustThreshold();\n }\n\n /**\n * Trim window to size\n */\n private trimWindow(): void {\n if (this.errorRateWindow.length > this.windowSize) {\n this.errorRateWindow.shift();\n }\n }\n\n /**\n * Adjust threshold based on error rate\n */\n private adjustThreshold(): void {\n const errorRate = this.getWindowErrorRate();\n\n // Increase threshold if error rate is low\n if (errorRate < 0.1) {\n this.adaptiveThreshold = Math.min(this.adaptiveThreshold + 1, 20);\n }\n // Decrease threshold if error rate is high\n else if (errorRate > 0.5) {\n this.adaptiveThreshold = Math.max(this.adaptiveThreshold - 1, 2);\n }\n\n // Sync adaptive threshold to parent config so it actually takes effect\n this.config.failureThreshold = this.adaptiveThreshold;\n }\n\n /**\n * Get error rate in window\n */\n private getWindowErrorRate(): number {\n if (this.errorRateWindow.length === 0) return 0;\n\n const errors = this.errorRateWindow.reduce((sum, val) => sum + val, 0);\n return errors / this.errorRateWindow.length;\n }\n\n /**\n * Get adaptive threshold\n */\n getAdaptiveThreshold(): number {\n return this.adaptiveThreshold;\n }\n}\n\n/**\n * Bulkhead pattern - limit concurrent executions\n */\nexport class Bulkhead {\n private activeRequests: number = 0;\n private queue: Array<() => void> = [];\n private maxConcurrent: number;\n private maxQueue: number;\n\n constructor(maxConcurrent: number = 10, maxQueue: number = 100) {\n this.maxConcurrent = maxConcurrent;\n this.maxQueue = maxQueue;\n }\n\n /**\n * Execute with bulkhead\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check if at capacity\n if (this.activeRequests >= this.maxConcurrent) {\n // Check queue capacity\n if (this.queue.length >= this.maxQueue) {\n throw new Error('Bulkhead queue is full');\n }\n\n // Wait for slot\n await new Promise<void>((resolve) => {\n this.queue.push(resolve);\n });\n }\n\n this.activeRequests++;\n\n try {\n return await fn();\n } finally {\n this.activeRequests--;\n\n // Process queue\n const next = this.queue.shift();\n if (next) {\n next();\n }\n }\n }\n\n /**\n * Get active requests\n */\n getActiveRequests(): number {\n return this.activeRequests;\n }\n\n /**\n * Get queue size\n */\n getQueueSize(): number {\n return this.queue.length;\n }\n\n /**\n * Get statistics\n */\n getStats(): {\n activeRequests: number;\n queueSize: number;\n maxConcurrent: number;\n maxQueue: number;\n } {\n return {\n activeRequests: this.activeRequests,\n queueSize: this.queue.length,\n maxConcurrent: this.maxConcurrent,\n maxQueue: this.maxQueue,\n };\n }\n}\n\n/**\n * Combined resilience wrapper\n */\nexport class ResilientOperation<T> {\n constructor(\n private fn: () => Promise<T>,\n private circuitBreaker?: CircuitBreaker,\n private bulkhead?: Bulkhead,\n ) {}\n\n /**\n * Execute with all resilience patterns\n */\n async execute(): Promise<T> {\n const executeFn = async () => {\n if (this.bulkhead) {\n return this.bulkhead.execute(this.fn);\n }\n return this.fn();\n };\n\n if (this.circuitBreaker) {\n return this.circuitBreaker.execute(executeFn);\n }\n\n return executeFn();\n }\n}\n\n/**\n * Create resilient function\n */\nexport function createResilientFunction<T>(\n fn: () => Promise<T>,\n options: {\n circuitBreaker?: CircuitBreakerConfig;\n bulkhead?: { maxConcurrent: number; maxQueue: number };\n } = {},\n): () => Promise<T> {\n const breaker = options.circuitBreaker ? new CircuitBreaker(options.circuitBreaker) : undefined;\n\n const bulkhead = options.bulkhead\n ? new Bulkhead(options.bulkhead.maxConcurrent, options.bulkhead.maxQueue)\n : undefined;\n\n const operation = new ResilientOperation(fn, breaker, bulkhead);\n\n return () => operation.execute();\n}\n","/**\n * Retry Logic for API Calls\n *\n * Implements exponential backoff and retry strategies\n */\n\nimport { randomInt } from 'node:crypto';\nimport { getResilienceLogger } from './logger.js';\n\nexport interface HttpError extends Error {\n statusCode?: number;\n response?: Response;\n}\n\nexport interface RetryConfig {\n maxRetries?: number;\n baseDelay?: number;\n maxDelay?: number;\n exponentialBackoff?: boolean;\n jitter?: boolean;\n retryableErrors?: (error: Error) => boolean;\n onRetry?: (error: Error, attempt: number) => void;\n}\n\nexport interface RetryOptions {\n signal?: AbortSignal;\n}\n\nconst DEFAULT_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n exponentialBackoff: true,\n jitter: true,\n retryableErrors: (error: Error) => {\n // Check for explicit non-retryable status codes (4xx client errors)\n if ('statusCode' in error) {\n const statusCode = (error as HttpError).statusCode;\n // Don't retry 4xx errors except 408 (timeout) and 429 (rate limit)\n if (statusCode !== undefined && statusCode >= 400 && statusCode < 500) {\n return statusCode === 408 || statusCode === 429;\n }\n }\n // Retry all other errors by default (network errors, 5xx, generic errors)\n return true;\n },\n onRetry: () => {\n // No-op default — consumers override via config\n },\n};\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retry<T>(\n fn: () => Promise<T>,\n config: RetryConfig = {},\n options: RetryOptions = {},\n): Promise<T> {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n let lastError: Error = new Error('Retry failed');\n\n for (let attempt = 0; attempt <= mergedConfig.maxRetries; attempt++) {\n try {\n // Check if aborted\n if (options.signal?.aborted) {\n throw new Error('Request aborted');\n }\n\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry if it's the last attempt\n if (attempt === mergedConfig.maxRetries) {\n throw lastError;\n }\n\n // Don't retry if error is not retryable\n if (!mergedConfig.retryableErrors(lastError)) {\n throw lastError;\n }\n\n // Call retry callback\n mergedConfig.onRetry(lastError, attempt + 1);\n\n // Calculate delay\n const delay = calculateDelay(\n attempt,\n mergedConfig.baseDelay,\n mergedConfig.maxDelay,\n mergedConfig.exponentialBackoff,\n mergedConfig.jitter,\n );\n\n // Wait before retrying\n await sleep(delay, options.signal);\n }\n }\n\n throw lastError;\n}\n\n/**\n * Calculate retry delay with exponential backoff\n */\nexport function calculateDelay(\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n exponentialBackoff: boolean,\n jitter: boolean,\n): number {\n let delay = baseDelay;\n\n if (exponentialBackoff) {\n // Exponential backoff: 2^attempt * baseDelay\n delay = Math.min(baseDelay * 2 ** attempt, maxDelay);\n }\n\n if (jitter) {\n // Add cryptographically random jitter (±25%), clamped to maxDelay\n const jitterAmount = Math.ceil(delay * 0.25);\n if (jitterAmount > 0) {\n delay = delay + randomInt(jitterAmount * 2 + 1) - jitterAmount;\n }\n }\n\n return Math.floor(Math.min(delay, maxDelay));\n}\n\n/**\n * Sleep with abort support\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error('Request aborted'));\n return;\n }\n\n const timeout = setTimeout(resolve, ms);\n\n if (signal) {\n signal.addEventListener('abort', () => {\n clearTimeout(timeout);\n reject(new Error('Request aborted'));\n });\n }\n });\n}\n\n/**\n * Retry wrapper for fetch\n */\nexport async function fetchWithRetry(\n url: string,\n init?: RequestInit,\n config?: RetryConfig,\n): Promise<Response> {\n const abortController = new AbortController();\n const signal = init?.signal || abortController.signal;\n\n return retry(\n async () => {\n const response = await fetch(url, {\n ...init,\n signal,\n });\n\n // Throw on error status\n if (!response.ok) {\n const error = new Error(`HTTP ${response.status}: ${response.statusText}`) as HttpError;\n error.statusCode = response.status;\n error.response = response;\n throw error;\n }\n\n return response;\n },\n {\n ...config,\n retryableErrors: (error) => {\n // Check custom retryable errors first\n if (config?.retryableErrors && !config.retryableErrors(error)) {\n return false;\n }\n\n // Don't retry 4xx errors (except 408, 429)\n if ('statusCode' in error) {\n const statusCode = (error as HttpError).statusCode;\n if (statusCode !== undefined && statusCode >= 400 && statusCode < 500) {\n return statusCode === 408 || statusCode === 429;\n }\n }\n\n return true;\n },\n },\n { signal },\n );\n}\n\n/**\n * Retry wrapper class\n */\nexport class RetryableOperation<T> {\n private config: Required<RetryConfig>;\n private abortController: AbortController;\n private attempts: number = 0;\n private lastError?: Error;\n\n constructor(\n private fn: () => Promise<T>,\n config: RetryConfig = {},\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.abortController = new AbortController();\n }\n\n /**\n * Execute with retry\n */\n async execute(): Promise<T> {\n return retry(this.fn, this.config, { signal: this.abortController.signal });\n }\n\n /**\n * Abort operation\n */\n abort(): void {\n this.abortController.abort();\n }\n\n /**\n * Get retry statistics\n */\n getStats(): {\n attempts: number;\n lastError?: Error;\n } {\n return {\n attempts: this.attempts,\n lastError: this.lastError,\n };\n }\n}\n\n/**\n * Retry decorator\n */\nexport function Retryable(config?: RetryConfig) {\n return (_target: object, _propertyKey: string, descriptor: PropertyDescriptor) => {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (...args: unknown[]) {\n return retry(() => originalMethod.apply(this, args), config);\n };\n\n return descriptor;\n };\n}\n\n/**\n * Create retry middleware for API client\n */\nexport function createRetryMiddleware<TRequest = unknown, TResponse = unknown>(\n config: RetryConfig = {},\n) {\n return async (_request: TRequest, next: () => Promise<TResponse>): Promise<TResponse> => {\n return retry(next, config);\n };\n}\n\n/**\n * Batch retry - retry multiple operations\n */\nexport async function retryBatch<T>(\n operations: Array<() => Promise<T>>,\n config: RetryConfig = {},\n): Promise<Array<T | Error>> {\n return Promise.all(\n operations.map(async (op) => {\n try {\n return await retry(op, config);\n } catch (error) {\n return error instanceof Error ? error : new Error(String(error));\n }\n }),\n );\n}\n\n/**\n * Retry with fallback\n */\nexport async function retryWithFallback<T>(\n primary: () => Promise<T>,\n fallback: () => Promise<T>,\n config: RetryConfig = {},\n): Promise<T> {\n try {\n return await retry(primary, config);\n } catch (error) {\n getResilienceLogger().warn('Primary operation failed, trying fallback', {\n error: error instanceof Error ? error.message : String(error),\n });\n return fallback();\n }\n}\n\n/**\n * Conditional retry - only retry if condition is met\n */\nexport async function retryIf<T>(\n fn: () => Promise<T>,\n condition: (error: Error, attempt: number) => boolean,\n config: RetryConfig = {},\n): Promise<T> {\n return retry(fn, {\n ...config,\n retryableErrors: (error) => {\n // Check original retryable condition first\n const originalCheck =\n config.retryableErrors?.(error) ?? DEFAULT_CONFIG.retryableErrors(error);\n if (!originalCheck) return false;\n\n // Then check custom condition\n return condition(error, 0);\n },\n });\n}\n\n/**\n * Retry until condition is met\n */\nexport async function retryUntil<T>(\n fn: () => Promise<T>,\n predicate: (result: T) => boolean,\n config: RetryConfig = {},\n maxAttempts: number = 10,\n): Promise<T> {\n let attempts = 0;\n\n while (attempts < maxAttempts) {\n try {\n const result = await fn();\n\n if (predicate(result)) {\n return result;\n }\n\n // Result doesn't match predicate, treat as retryable error\n attempts++;\n\n if (attempts >= maxAttempts) {\n throw new Error('Max attempts reached without matching predicate');\n }\n\n const delay = calculateDelay(\n attempts - 1,\n config.baseDelay ?? DEFAULT_CONFIG.baseDelay,\n config.maxDelay ?? DEFAULT_CONFIG.maxDelay,\n config.exponentialBackoff ?? DEFAULT_CONFIG.exponentialBackoff,\n config.jitter ?? DEFAULT_CONFIG.jitter,\n );\n\n await sleep(delay);\n } catch (error) {\n attempts++;\n\n if (attempts >= maxAttempts) {\n throw error;\n }\n\n const delay = calculateDelay(\n attempts - 1,\n config.baseDelay ?? DEFAULT_CONFIG.baseDelay,\n config.maxDelay ?? DEFAULT_CONFIG.maxDelay,\n config.exponentialBackoff ?? DEFAULT_CONFIG.exponentialBackoff,\n config.jitter ?? DEFAULT_CONFIG.jitter,\n );\n\n await sleep(delay);\n }\n }\n\n throw new Error('Max attempts reached');\n}\n\n/**\n * Exponential backoff iterator\n */\nexport class ExponentialBackoff implements AsyncIterable<number> {\n constructor(\n private baseDelay: number = 1000,\n private maxDelay: number = 30000,\n private maxAttempts: number = 10,\n private jitter: boolean = true,\n ) {}\n\n async *[Symbol.asyncIterator](): AsyncIterator<number> {\n for (let attempt = 0; attempt < this.maxAttempts; attempt++) {\n const delay = calculateDelay(attempt, this.baseDelay, this.maxDelay, true, this.jitter);\n\n yield delay;\n\n await sleep(delay);\n }\n }\n}\n\n/**\n * Retry policy builder\n */\nexport class RetryPolicyBuilder {\n private config: Partial<Required<RetryConfig>> = {};\n\n /**\n * Set max retries\n */\n maxRetries(count: number): this {\n this.config.maxRetries = count;\n return this;\n }\n\n /**\n * Set base delay\n */\n baseDelay(ms: number): this {\n this.config.baseDelay = ms;\n return this;\n }\n\n /**\n * Set max delay\n */\n maxDelay(ms: number): this {\n this.config.maxDelay = ms;\n return this;\n }\n\n /**\n * Enable/disable exponential backoff\n */\n exponentialBackoff(enabled: boolean = true): this {\n this.config.exponentialBackoff = enabled;\n return this;\n }\n\n /**\n * Enable/disable jitter\n */\n jitter(enabled: boolean = true): this {\n this.config.jitter = enabled;\n return this;\n }\n\n /**\n * Set custom retryable errors function\n */\n retryOn(fn: (error: Error) => boolean): this {\n this.config.retryableErrors = fn;\n return this;\n }\n\n /**\n * Set retry callback\n */\n onRetry(fn: (error: Error, attempt: number) => void): this {\n this.config.onRetry = fn;\n return this;\n }\n\n /**\n * Build retry config\n */\n build(): RetryConfig {\n return this.config;\n }\n\n /**\n * Execute function with built policy\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n return retry(fn, this.build());\n }\n}\n\n/**\n * Common retry policies\n */\nexport const RetryPolicies = {\n /**\n * Default policy - 3 retries with exponential backoff\n */\n default: (): RetryConfig => ({\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n exponentialBackoff: true,\n jitter: true,\n }),\n\n /**\n * Aggressive policy - more retries, faster backoff\n */\n aggressive: (): RetryConfig => ({\n maxRetries: 5,\n baseDelay: 500,\n maxDelay: 10000,\n exponentialBackoff: true,\n jitter: true,\n }),\n\n /**\n * Conservative policy - fewer retries, longer backoff\n */\n conservative: (): RetryConfig => ({\n maxRetries: 2,\n baseDelay: 2000,\n maxDelay: 60000,\n exponentialBackoff: true,\n jitter: true,\n }),\n\n /**\n * Linear backoff policy\n */\n linear: (): RetryConfig => ({\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 10000,\n exponentialBackoff: false,\n jitter: false,\n }),\n\n /**\n * Immediate retry policy - no delay\n */\n immediate: (): RetryConfig => ({\n maxRetries: 3,\n baseDelay: 0,\n maxDelay: 0,\n exponentialBackoff: false,\n jitter: false,\n }),\n\n /**\n * Network error only policy\n */\n networkOnly: (): RetryConfig => ({\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n exponentialBackoff: true,\n jitter: true,\n retryableErrors: (error) => error.name === 'NetworkError',\n }),\n\n /**\n * Idempotent operations policy (safe to retry)\n */\n idempotent: (): RetryConfig => ({\n maxRetries: 5,\n baseDelay: 1000,\n maxDelay: 30000,\n exponentialBackoff: true,\n jitter: true,\n }),\n};\n\n/**\n * Global retry configuration\n */\nclass GlobalRetryConfig {\n private config: RetryConfig = RetryPolicies.default();\n\n /**\n * Set global retry config\n */\n setConfig(config: RetryConfig): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Get global retry config\n */\n getConfig(): RetryConfig {\n return this.config;\n }\n\n /**\n * Reset to default config\n */\n reset(): void {\n this.config = RetryPolicies.default();\n }\n}\n\nexport const globalRetryConfig = new GlobalRetryConfig();\n"],"mappings":"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","names":["DEFAULT_CONFIG"]}
1
+ {"version":3,"sources":["../src/logger.ts","../src/circuit-breaker.ts","../src/circuit-breaker-store.ts","../src/retry.ts"],"sourcesContent":["/**\n * Internal logger for @revealui/resilience.\n *\n * Defaults to `console`. Consumers should call `configureResilienceLogger()`\n * to supply a structured logger (e.g. from `@revealui/utils/logger`).\n */\n\nexport interface ResilienceLogger {\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n debug(message: string, ...args: unknown[]): void;\n}\n\nlet resilienceLogger: ResilienceLogger = console;\n\n/**\n * Replace the default console logger with a structured logger.\n */\nexport function configureResilienceLogger(logger: ResilienceLogger): void {\n resilienceLogger = logger;\n}\n\n/**\n * Get the current resilience logger instance.\n */\nexport function getResilienceLogger(): ResilienceLogger {\n return resilienceLogger;\n}\n","/**\n * Circuit Breaker Pattern\n *\n * Prevents cascading failures by stopping requests to failing services\n */\n\nimport { getResilienceLogger } from './logger.js';\nimport type { HttpError } from './retry.js';\n\nexport type CircuitState = 'closed' | 'open' | 'half-open';\n\nexport interface CircuitBreakerConfig {\n failureThreshold?: number;\n successThreshold?: number;\n timeout?: number;\n resetTimeout?: number;\n volumeThreshold?: number;\n errorFilter?: (error: Error) => boolean;\n onStateChange?: (state: CircuitState) => void;\n onTrip?: () => void;\n onReset?: () => void;\n}\n\nexport interface CircuitBreakerStats {\n [key: string]: unknown;\n state: CircuitState;\n failures: number;\n successes: number;\n consecutiveFailures: number;\n consecutiveSuccesses: number;\n totalCalls: number;\n totalFailures: number;\n totalSuccesses: number;\n lastFailureTime?: number;\n lastSuccessTime?: number;\n stateChangedAt: number;\n}\n\nconst DEFAULT_CONFIG: Required<CircuitBreakerConfig> = {\n failureThreshold: 5,\n successThreshold: 2,\n timeout: 60000,\n resetTimeout: 30000,\n volumeThreshold: 10,\n errorFilter: () => true,\n onStateChange: () => {\n // No-op default — consumers override via config\n },\n onTrip: () => {\n // No-op default — consumers override via config\n },\n onReset: () => {\n // No-op default — consumers override via config\n },\n};\n\n/**\n * Circuit Breaker implementation\n */\nexport class CircuitBreaker {\n private state: CircuitState = 'closed';\n private failures: number = 0;\n private successes: number = 0;\n private consecutiveFailures: number = 0;\n private consecutiveSuccesses: number = 0;\n private totalCalls: number = 0;\n private totalFailures: number = 0;\n private totalSuccesses: number = 0;\n private lastFailureTime?: number;\n private lastSuccessTime?: number;\n private stateChangedAt: number = Date.now();\n private resetTimer?: NodeJS.Timeout;\n protected config: Required<CircuitBreakerConfig>;\n\n constructor(config: CircuitBreakerConfig = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Execute function with circuit breaker\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check if circuit is open\n if (this.state === 'open') {\n // Check if reset timeout has passed\n if (Date.now() - this.stateChangedAt >= this.config.resetTimeout) {\n this.transitionTo('half-open');\n } else {\n throw new CircuitBreakerOpenError('Circuit breaker is open');\n }\n }\n\n this.totalCalls++;\n\n try {\n const result = await fn();\n this.onSuccess();\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n this.onFailure(err);\n throw error;\n }\n }\n\n /**\n * Handle successful execution\n */\n private onSuccess(): void {\n this.successes++;\n this.consecutiveSuccesses++;\n this.totalSuccesses++;\n this.consecutiveFailures = 0;\n this.lastSuccessTime = Date.now();\n\n if (this.state === 'half-open') {\n // Check if we can close the circuit\n if (this.consecutiveSuccesses >= this.config.successThreshold) {\n this.transitionTo('closed');\n }\n }\n\n // Reset failure count in closed state\n if (this.state === 'closed') {\n this.failures = 0;\n }\n }\n\n /**\n * Handle failed execution\n */\n private onFailure(error: Error): void {\n // Check if error should count\n if (!this.config.errorFilter(error)) {\n return;\n }\n\n this.failures++;\n this.consecutiveFailures++;\n this.totalFailures++;\n this.consecutiveSuccesses = 0;\n this.lastFailureTime = Date.now();\n\n if (this.state === 'half-open') {\n // Immediately open circuit on failure in half-open state\n this.transitionTo('open');\n } else if (this.state === 'closed') {\n // Check if we should open the circuit\n if (\n this.consecutiveFailures >= this.config.failureThreshold &&\n this.totalCalls >= this.config.volumeThreshold\n ) {\n this.transitionTo('open');\n }\n }\n }\n\n /**\n * Transition to new state\n */\n private transitionTo(newState: CircuitState): void {\n if (this.state === newState) return;\n\n const oldState = this.state;\n this.state = newState;\n this.stateChangedAt = Date.now();\n\n // Reset counters\n if (newState === 'half-open' || newState === 'closed') {\n this.consecutiveFailures = 0;\n this.consecutiveSuccesses = 0;\n }\n\n // Clear reset timer\n if (this.resetTimer) {\n clearTimeout(this.resetTimer);\n this.resetTimer = undefined;\n }\n\n // Set reset timer for open state\n if (newState === 'open') {\n this.resetTimer = setTimeout(() => {\n this.transitionTo('half-open');\n }, this.config.resetTimeout);\n\n this.config.onTrip();\n }\n\n // Circuit reset\n if (newState === 'closed' && oldState === 'half-open') {\n this.failures = 0;\n this.config.onReset();\n }\n\n this.config.onStateChange(newState);\n\n getResilienceLogger().info(\n `Circuit breaker state changed: ${oldState} -> ${newState}`,\n this.getStats(),\n );\n }\n\n /**\n * Get current state\n */\n getState(): CircuitState {\n return this.state;\n }\n\n /**\n * Get statistics\n */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n consecutiveFailures: this.consecutiveFailures,\n consecutiveSuccesses: this.consecutiveSuccesses,\n totalCalls: this.totalCalls,\n totalFailures: this.totalFailures,\n totalSuccesses: this.totalSuccesses,\n lastFailureTime: this.lastFailureTime,\n lastSuccessTime: this.lastSuccessTime,\n stateChangedAt: this.stateChangedAt,\n };\n }\n\n /**\n * Manually open circuit\n */\n trip(): void {\n this.transitionTo('open');\n }\n\n /**\n * Manually close circuit\n */\n reset(): void {\n this.failures = 0;\n this.successes = 0;\n this.consecutiveFailures = 0;\n this.consecutiveSuccesses = 0;\n this.transitionTo('closed');\n }\n\n /**\n * Force state to half-open\n */\n halfOpen(): void {\n this.transitionTo('half-open');\n }\n\n /**\n * Check if circuit is open\n */\n isOpen(): boolean {\n return this.state === 'open';\n }\n\n /**\n * Check if circuit is closed\n */\n isClosed(): boolean {\n return this.state === 'closed';\n }\n\n /**\n * Check if circuit is half-open\n */\n isHalfOpen(): boolean {\n return this.state === 'half-open';\n }\n\n /**\n * Get failure rate\n */\n getFailureRate(): number {\n if (this.totalCalls === 0) return 0;\n return this.totalFailures / this.totalCalls;\n }\n\n /**\n * Get success rate\n */\n getSuccessRate(): number {\n if (this.totalCalls === 0) return 0;\n return this.totalSuccesses / this.totalCalls;\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n if (this.resetTimer) {\n clearTimeout(this.resetTimer);\n }\n }\n}\n\n/**\n * Circuit breaker open error\n */\nexport class CircuitBreakerOpenError extends Error {\n constructor(message: string = 'Circuit breaker is open') {\n super(message);\n this.name = 'CircuitBreakerOpenError';\n }\n}\n\n/**\n * Circuit breaker registry\n */\nexport class CircuitBreakerRegistry {\n private breakers: Map<string, CircuitBreaker> = new Map();\n\n /**\n * Get or create circuit breaker\n */\n get(name: string, config?: CircuitBreakerConfig): CircuitBreaker {\n let breaker = this.breakers.get(name);\n\n if (!breaker) {\n breaker = new CircuitBreaker(config);\n this.breakers.set(name, breaker);\n }\n\n return breaker;\n }\n\n /**\n * Check if breaker exists\n */\n has(name: string): boolean {\n return this.breakers.has(name);\n }\n\n /**\n * Remove circuit breaker\n */\n remove(name: string): boolean {\n const breaker = this.breakers.get(name);\n if (breaker) {\n breaker.destroy();\n return this.breakers.delete(name);\n }\n return false;\n }\n\n /**\n * Get all breakers\n */\n getAll(): Map<string, CircuitBreaker> {\n return new Map(this.breakers);\n }\n\n /**\n * Get all statistics\n */\n getAllStats(): Record<string, CircuitBreakerStats> {\n const stats: Record<string, CircuitBreakerStats> = {};\n\n for (const [name, breaker] of this.breakers) {\n stats[name] = breaker.getStats();\n }\n\n return stats;\n }\n\n /**\n * Reset all breakers\n */\n resetAll(): void {\n for (const breaker of this.breakers.values()) {\n breaker.reset();\n }\n }\n\n /**\n * Clear all breakers\n */\n clear(): void {\n for (const breaker of this.breakers.values()) {\n breaker.destroy();\n }\n this.breakers.clear();\n }\n}\n\n/**\n * Global circuit breaker registry\n */\nexport const circuitBreakerRegistry = new CircuitBreakerRegistry();\n\n/**\n * Create circuit breaker decorator\n */\nexport function CircuitBreak(nameOrConfig: string | CircuitBreakerConfig = {}) {\n return (target: object, propertyKey: string, descriptor: PropertyDescriptor) => {\n const originalMethod = descriptor.value;\n const name =\n typeof nameOrConfig === 'string'\n ? nameOrConfig\n : `${(target as { constructor: { name: string } }).constructor.name}.${propertyKey}`;\n const config = typeof nameOrConfig === 'object' ? nameOrConfig : undefined;\n\n descriptor.value = async function (...args: unknown[]) {\n const breaker = circuitBreakerRegistry.get(name, config);\n return breaker.execute(() => originalMethod.apply(this, args));\n };\n\n return descriptor;\n };\n}\n\n/**\n * Execute with circuit breaker\n */\nexport async function withCircuitBreaker<T>(\n name: string,\n fn: () => Promise<T>,\n config?: CircuitBreakerConfig,\n): Promise<T> {\n const breaker = circuitBreakerRegistry.get(name, config);\n return breaker.execute(fn);\n}\n\n/**\n * Create circuit breaker middleware\n */\nexport function createCircuitBreakerMiddleware<TRequest = unknown, TResponse = unknown>(\n name: string,\n config?: CircuitBreakerConfig,\n) {\n const breaker = circuitBreakerRegistry.get(name, config);\n\n return async (_request: TRequest, next: () => Promise<TResponse>): Promise<TResponse> => {\n return breaker.execute(next);\n };\n}\n\n/**\n * Circuit breaker for fetch\n */\nexport async function fetchWithCircuitBreaker(\n name: string,\n url: string,\n init?: RequestInit,\n config?: CircuitBreakerConfig,\n): Promise<Response> {\n const breaker = circuitBreakerRegistry.get(name, config);\n\n return breaker.execute(async () => {\n const response = await fetch(url, init);\n\n // Treat 5xx errors as failures\n if (response.status >= 500) {\n const error = new Error(`HTTP ${response.status}: ${response.statusText}`) as HttpError;\n error.statusCode = response.status;\n throw error;\n }\n\n return response;\n });\n}\n\n/**\n * Adaptive circuit breaker with dynamic thresholds\n */\nexport class AdaptiveCircuitBreaker extends CircuitBreaker {\n private errorRateWindow: number[] = [];\n private windowSize: number = 100;\n private adaptiveThreshold: number;\n\n constructor(config: CircuitBreakerConfig = {}) {\n super(config);\n this.adaptiveThreshold = config.failureThreshold || 5;\n }\n\n /**\n * Execute with adaptive thresholds\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n try {\n const result = await super.execute(fn);\n this.recordSuccess();\n return result;\n } catch (error) {\n this.recordFailure();\n throw error;\n }\n }\n\n /**\n * Record success in window\n */\n private recordSuccess(): void {\n this.errorRateWindow.push(0);\n this.trimWindow();\n this.adjustThreshold();\n }\n\n /**\n * Record failure in window\n */\n private recordFailure(): void {\n this.errorRateWindow.push(1);\n this.trimWindow();\n this.adjustThreshold();\n }\n\n /**\n * Trim window to size\n */\n private trimWindow(): void {\n if (this.errorRateWindow.length > this.windowSize) {\n this.errorRateWindow.shift();\n }\n }\n\n /**\n * Adjust threshold based on error rate\n */\n private adjustThreshold(): void {\n const errorRate = this.getWindowErrorRate();\n\n // Increase threshold if error rate is low\n if (errorRate < 0.1) {\n this.adaptiveThreshold = Math.min(this.adaptiveThreshold + 1, 20);\n }\n // Decrease threshold if error rate is high\n else if (errorRate > 0.5) {\n this.adaptiveThreshold = Math.max(this.adaptiveThreshold - 1, 2);\n }\n\n // Sync adaptive threshold to parent config so it actually takes effect\n this.config.failureThreshold = this.adaptiveThreshold;\n }\n\n /**\n * Get error rate in window\n */\n private getWindowErrorRate(): number {\n if (this.errorRateWindow.length === 0) return 0;\n\n const errors = this.errorRateWindow.reduce((sum, val) => sum + val, 0);\n return errors / this.errorRateWindow.length;\n }\n\n /**\n * Get adaptive threshold\n */\n getAdaptiveThreshold(): number {\n return this.adaptiveThreshold;\n }\n}\n\n/**\n * Bulkhead pattern - limit concurrent executions\n */\nexport class Bulkhead {\n private activeRequests: number = 0;\n private queue: Array<() => void> = [];\n private maxConcurrent: number;\n private maxQueue: number;\n\n constructor(maxConcurrent: number = 10, maxQueue: number = 100) {\n this.maxConcurrent = maxConcurrent;\n this.maxQueue = maxQueue;\n }\n\n /**\n * Execute with bulkhead\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check if at capacity\n if (this.activeRequests >= this.maxConcurrent) {\n // Check queue capacity\n if (this.queue.length >= this.maxQueue) {\n throw new Error('Bulkhead queue is full');\n }\n\n // Wait for slot\n await new Promise<void>((resolve) => {\n this.queue.push(resolve);\n });\n }\n\n this.activeRequests++;\n\n try {\n return await fn();\n } finally {\n this.activeRequests--;\n\n // Process queue\n const next = this.queue.shift();\n if (next) {\n next();\n }\n }\n }\n\n /**\n * Get active requests\n */\n getActiveRequests(): number {\n return this.activeRequests;\n }\n\n /**\n * Get queue size\n */\n getQueueSize(): number {\n return this.queue.length;\n }\n\n /**\n * Get statistics\n */\n getStats(): {\n activeRequests: number;\n queueSize: number;\n maxConcurrent: number;\n maxQueue: number;\n } {\n return {\n activeRequests: this.activeRequests,\n queueSize: this.queue.length,\n maxConcurrent: this.maxConcurrent,\n maxQueue: this.maxQueue,\n };\n }\n}\n\n/**\n * Combined resilience wrapper\n */\nexport class ResilientOperation<T> {\n constructor(\n private fn: () => Promise<T>,\n private circuitBreaker?: CircuitBreaker,\n private bulkhead?: Bulkhead,\n ) {}\n\n /**\n * Execute with all resilience patterns\n */\n async execute(): Promise<T> {\n const executeFn = async () => {\n if (this.bulkhead) {\n return this.bulkhead.execute(this.fn);\n }\n return this.fn();\n };\n\n if (this.circuitBreaker) {\n return this.circuitBreaker.execute(executeFn);\n }\n\n return executeFn();\n }\n}\n\n/**\n * Create resilient function\n */\nexport function createResilientFunction<T>(\n fn: () => Promise<T>,\n options: {\n circuitBreaker?: CircuitBreakerConfig;\n bulkhead?: { maxConcurrent: number; maxQueue: number };\n } = {},\n): () => Promise<T> {\n const breaker = options.circuitBreaker ? new CircuitBreaker(options.circuitBreaker) : undefined;\n\n const bulkhead = options.bulkhead\n ? new Bulkhead(options.bulkhead.maxConcurrent, options.bulkhead.maxQueue)\n : undefined;\n\n const operation = new ResilientOperation(fn, breaker, bulkhead);\n\n return () => operation.execute();\n}\n","/**\n * Circuit Breaker State Store — Pluggable backends for circuit breaker persistence.\n *\n * - InMemoryCircuitBreakerStore: Map-backed, single-instance (default)\n * - PGliteCircuitBreakerStore: SQL-backed via PGlite, persistent across restarts\n *\n * Stores only the durable state needed for recovery: state, counters, timestamps.\n * Timers and callbacks remain in-memory on the CircuitBreaker instance.\n */\n\nimport type { CircuitState } from './circuit-breaker.js';\n\n// =============================================================================\n// Store interface\n// =============================================================================\n\nexport interface CircuitBreakerSnapshot {\n state: CircuitState;\n failureCount: number;\n successCount: number;\n consecutiveFailures: number;\n consecutiveSuccesses: number;\n lastFailureAt: number;\n lastSuccessAt: number;\n stateChangedAt: number;\n}\n\n/**\n * Pluggable storage backend for circuit breaker state.\n * Each service gets its own named breaker.\n */\nexport interface CircuitBreakerStore {\n /** Load the state for a named service, or null if no state exists. */\n load(name: string): Promise<CircuitBreakerSnapshot | null>;\n\n /** Persist a snapshot for a named service. */\n save(name: string, snapshot: CircuitBreakerSnapshot): Promise<void>;\n\n /** Remove state for a named service. Returns true if it existed. */\n remove(name: string): Promise<boolean>;\n\n /** Clear all circuit breaker state. */\n clear(): Promise<void>;\n\n /** Release any resources. */\n close(): Promise<void>;\n}\n\n// =============================================================================\n// In-memory store (Map-backed, default)\n// =============================================================================\n\nexport class InMemoryCircuitBreakerStore implements CircuitBreakerStore {\n private state = new Map<string, CircuitBreakerSnapshot>();\n\n async load(name: string): Promise<CircuitBreakerSnapshot | null> {\n const snapshot = this.state.get(name);\n return snapshot ? { ...snapshot } : null;\n }\n\n async save(name: string, snapshot: CircuitBreakerSnapshot): Promise<void> {\n this.state.set(name, { ...snapshot });\n }\n\n async remove(name: string): Promise<boolean> {\n return this.state.delete(name);\n }\n\n async clear(): Promise<void> {\n this.state.clear();\n }\n\n async close(): Promise<void> {\n this.state.clear();\n }\n}\n\n// =============================================================================\n// PGlite store (SQL-backed)\n// =============================================================================\n\n/** Minimal PGlite interface — avoids importing the full @electric-sql/pglite package. */\ninterface PGliteInstance {\n exec(query: string): Promise<unknown>;\n query<T = Record<string, unknown>>(query: string, params?: unknown[]): Promise<{ rows: T[] }>;\n close(): Promise<void>;\n}\n\nconst CREATE_CB_TABLE_SQL = `\n CREATE TABLE IF NOT EXISTS _circuit_breaker_state (\n name TEXT PRIMARY KEY,\n state TEXT NOT NULL DEFAULT 'closed',\n failure_count INTEGER NOT NULL DEFAULT 0,\n success_count INTEGER NOT NULL DEFAULT 0,\n consecutive_failures INTEGER NOT NULL DEFAULT 0,\n consecutive_successes INTEGER NOT NULL DEFAULT 0,\n last_failure_at BIGINT NOT NULL DEFAULT 0,\n last_success_at BIGINT NOT NULL DEFAULT 0,\n state_changed_at BIGINT NOT NULL DEFAULT 0\n );\n`;\n\ninterface PGliteCircuitBreakerStoreOptions {\n /** PGlite instance (caller owns lifecycle unless closeOnDestroy is true). */\n db: PGliteInstance;\n /** Close the PGlite instance when close() is called (default: false). */\n closeOnDestroy?: boolean;\n}\n\ninterface CBRow {\n state: string;\n failure_count: number;\n success_count: number;\n consecutive_failures: number;\n consecutive_successes: number;\n last_failure_at: string;\n last_success_at: string;\n state_changed_at: string;\n}\n\nexport class PGliteCircuitBreakerStore implements CircuitBreakerStore {\n private db: PGliteInstance;\n private ready: Promise<void>;\n private closeOnDestroy: boolean;\n\n constructor(options: PGliteCircuitBreakerStoreOptions) {\n this.db = options.db;\n this.closeOnDestroy = options.closeOnDestroy ?? false;\n this.ready = this.init();\n }\n\n private async init(): Promise<void> {\n await this.db.exec(CREATE_CB_TABLE_SQL);\n }\n\n async load(name: string): Promise<CircuitBreakerSnapshot | null> {\n await this.ready;\n const result = await this.db.query<CBRow>(\n 'SELECT state, failure_count, success_count, consecutive_failures, consecutive_successes, last_failure_at, last_success_at, state_changed_at FROM _circuit_breaker_state WHERE name = $1',\n [name],\n );\n const row = result.rows[0];\n if (!row) return null;\n\n return {\n state: row.state as CircuitState,\n failureCount: row.failure_count,\n successCount: row.success_count,\n consecutiveFailures: row.consecutive_failures,\n consecutiveSuccesses: row.consecutive_successes,\n lastFailureAt: Number(row.last_failure_at),\n lastSuccessAt: Number(row.last_success_at),\n stateChangedAt: Number(row.state_changed_at),\n };\n }\n\n async save(name: string, snapshot: CircuitBreakerSnapshot): Promise<void> {\n await this.ready;\n await this.db.query(\n `INSERT INTO _circuit_breaker_state\n (name, state, failure_count, success_count, consecutive_failures, consecutive_successes, last_failure_at, last_success_at, state_changed_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)\n ON CONFLICT (name) DO UPDATE SET\n state = EXCLUDED.state,\n failure_count = EXCLUDED.failure_count,\n success_count = EXCLUDED.success_count,\n consecutive_failures = EXCLUDED.consecutive_failures,\n consecutive_successes = EXCLUDED.consecutive_successes,\n last_failure_at = EXCLUDED.last_failure_at,\n last_success_at = EXCLUDED.last_success_at,\n state_changed_at = EXCLUDED.state_changed_at`,\n [\n name,\n snapshot.state,\n snapshot.failureCount,\n snapshot.successCount,\n snapshot.consecutiveFailures,\n snapshot.consecutiveSuccesses,\n snapshot.lastFailureAt,\n snapshot.lastSuccessAt,\n snapshot.stateChangedAt,\n ],\n );\n }\n\n async remove(name: string): Promise<boolean> {\n await this.ready;\n const result = await this.db.query<{ count: string }>(\n `WITH deleted AS (DELETE FROM _circuit_breaker_state WHERE name = $1 RETURNING 1)\n SELECT count(*)::text AS count FROM deleted`,\n [name],\n );\n return Number.parseInt(result.rows[0]?.count ?? '0', 10) > 0;\n }\n\n async clear(): Promise<void> {\n await this.ready;\n await this.db.exec('DELETE FROM _circuit_breaker_state');\n }\n\n async close(): Promise<void> {\n if (this.closeOnDestroy) {\n await this.db.close();\n }\n }\n}\n","/**\n * Retry Logic for API Calls\n *\n * Implements exponential backoff and retry strategies\n */\n\nimport { randomInt } from 'node:crypto';\nimport { getResilienceLogger } from './logger.js';\n\nexport interface HttpError extends Error {\n statusCode?: number;\n response?: Response;\n}\n\nexport interface RetryConfig {\n maxRetries?: number;\n baseDelay?: number;\n maxDelay?: number;\n exponentialBackoff?: boolean;\n jitter?: boolean;\n retryableErrors?: (error: Error) => boolean;\n onRetry?: (error: Error, attempt: number) => void;\n}\n\nexport interface RetryOptions {\n signal?: AbortSignal;\n}\n\nconst DEFAULT_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n exponentialBackoff: true,\n jitter: true,\n retryableErrors: (error: Error) => {\n // Check for explicit non-retryable status codes (4xx client errors)\n if ('statusCode' in error) {\n const statusCode = (error as HttpError).statusCode;\n // Don't retry 4xx errors except 408 (timeout) and 429 (rate limit)\n if (statusCode !== undefined && statusCode >= 400 && statusCode < 500) {\n return statusCode === 408 || statusCode === 429;\n }\n }\n // Retry all other errors by default (network errors, 5xx, generic errors)\n return true;\n },\n onRetry: () => {\n // No-op default — consumers override via config\n },\n};\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retry<T>(\n fn: () => Promise<T>,\n config: RetryConfig = {},\n options: RetryOptions = {},\n): Promise<T> {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n let lastError: Error = new Error('Retry failed');\n\n for (let attempt = 0; attempt <= mergedConfig.maxRetries; attempt++) {\n try {\n // Check if aborted\n if (options.signal?.aborted) {\n throw new Error('Request aborted');\n }\n\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry if it's the last attempt\n if (attempt === mergedConfig.maxRetries) {\n throw lastError;\n }\n\n // Don't retry if error is not retryable\n if (!mergedConfig.retryableErrors(lastError)) {\n throw lastError;\n }\n\n // Call retry callback\n mergedConfig.onRetry(lastError, attempt + 1);\n\n // Calculate delay\n const delay = calculateDelay(\n attempt,\n mergedConfig.baseDelay,\n mergedConfig.maxDelay,\n mergedConfig.exponentialBackoff,\n mergedConfig.jitter,\n );\n\n // Wait before retrying\n await sleep(delay, options.signal);\n }\n }\n\n throw lastError;\n}\n\n/**\n * Calculate retry delay with exponential backoff\n */\nexport function calculateDelay(\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n exponentialBackoff: boolean,\n jitter: boolean,\n): number {\n let delay = baseDelay;\n\n if (exponentialBackoff) {\n // Exponential backoff: 2^attempt * baseDelay\n delay = Math.min(baseDelay * 2 ** attempt, maxDelay);\n }\n\n if (jitter) {\n // Add cryptographically random jitter (±25%), clamped to maxDelay\n const jitterAmount = Math.ceil(delay * 0.25);\n if (jitterAmount > 0) {\n delay = delay + randomInt(jitterAmount * 2 + 1) - jitterAmount;\n }\n }\n\n return Math.floor(Math.min(delay, maxDelay));\n}\n\n/**\n * Sleep with abort support\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error('Request aborted'));\n return;\n }\n\n const timeout = setTimeout(resolve, ms);\n\n if (signal) {\n signal.addEventListener('abort', () => {\n clearTimeout(timeout);\n reject(new Error('Request aborted'));\n });\n }\n });\n}\n\n/**\n * Retry wrapper for fetch\n */\nexport async function fetchWithRetry(\n url: string,\n init?: RequestInit,\n config?: RetryConfig,\n): Promise<Response> {\n const abortController = new AbortController();\n const signal = init?.signal || abortController.signal;\n\n return retry(\n async () => {\n const response = await fetch(url, {\n ...init,\n signal,\n });\n\n // Throw on error status\n if (!response.ok) {\n const error = new Error(`HTTP ${response.status}: ${response.statusText}`) as HttpError;\n error.statusCode = response.status;\n error.response = response;\n throw error;\n }\n\n return response;\n },\n {\n ...config,\n retryableErrors: (error) => {\n // Check custom retryable errors first\n if (config?.retryableErrors && !config.retryableErrors(error)) {\n return false;\n }\n\n // Don't retry 4xx errors (except 408, 429)\n if ('statusCode' in error) {\n const statusCode = (error as HttpError).statusCode;\n if (statusCode !== undefined && statusCode >= 400 && statusCode < 500) {\n return statusCode === 408 || statusCode === 429;\n }\n }\n\n return true;\n },\n },\n { signal },\n );\n}\n\n/**\n * Retry wrapper class\n */\nexport class RetryableOperation<T> {\n private config: Required<RetryConfig>;\n private abortController: AbortController;\n private attempts: number = 0;\n private lastError?: Error;\n\n constructor(\n private fn: () => Promise<T>,\n config: RetryConfig = {},\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.abortController = new AbortController();\n }\n\n /**\n * Execute with retry\n */\n async execute(): Promise<T> {\n return retry(this.fn, this.config, { signal: this.abortController.signal });\n }\n\n /**\n * Abort operation\n */\n abort(): void {\n this.abortController.abort();\n }\n\n /**\n * Get retry statistics\n */\n getStats(): {\n attempts: number;\n lastError?: Error;\n } {\n return {\n attempts: this.attempts,\n lastError: this.lastError,\n };\n }\n}\n\n/**\n * Retry decorator\n */\nexport function Retryable(config?: RetryConfig) {\n return (_target: object, _propertyKey: string, descriptor: PropertyDescriptor) => {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (...args: unknown[]) {\n return retry(() => originalMethod.apply(this, args), config);\n };\n\n return descriptor;\n };\n}\n\n/**\n * Create retry middleware for API client\n */\nexport function createRetryMiddleware<TRequest = unknown, TResponse = unknown>(\n config: RetryConfig = {},\n) {\n return async (_request: TRequest, next: () => Promise<TResponse>): Promise<TResponse> => {\n return retry(next, config);\n };\n}\n\n/**\n * Batch retry - retry multiple operations\n */\nexport async function retryBatch<T>(\n operations: Array<() => Promise<T>>,\n config: RetryConfig = {},\n): Promise<Array<T | Error>> {\n return Promise.all(\n operations.map(async (op) => {\n try {\n return await retry(op, config);\n } catch (error) {\n return error instanceof Error ? error : new Error(String(error));\n }\n }),\n );\n}\n\n/**\n * Retry with fallback\n */\nexport async function retryWithFallback<T>(\n primary: () => Promise<T>,\n fallback: () => Promise<T>,\n config: RetryConfig = {},\n): Promise<T> {\n try {\n return await retry(primary, config);\n } catch (error) {\n getResilienceLogger().warn('Primary operation failed, trying fallback', {\n error: error instanceof Error ? error.message : String(error),\n });\n return fallback();\n }\n}\n\n/**\n * Conditional retry - only retry if condition is met\n */\nexport async function retryIf<T>(\n fn: () => Promise<T>,\n condition: (error: Error, attempt: number) => boolean,\n config: RetryConfig = {},\n): Promise<T> {\n return retry(fn, {\n ...config,\n retryableErrors: (error) => {\n // Check original retryable condition first\n const originalCheck =\n config.retryableErrors?.(error) ?? DEFAULT_CONFIG.retryableErrors(error);\n if (!originalCheck) return false;\n\n // Then check custom condition\n return condition(error, 0);\n },\n });\n}\n\n/**\n * Retry until condition is met\n */\nexport async function retryUntil<T>(\n fn: () => Promise<T>,\n predicate: (result: T) => boolean,\n config: RetryConfig = {},\n maxAttempts: number = 10,\n): Promise<T> {\n let attempts = 0;\n\n while (attempts < maxAttempts) {\n try {\n const result = await fn();\n\n if (predicate(result)) {\n return result;\n }\n\n // Result doesn't match predicate, treat as retryable error\n attempts++;\n\n if (attempts >= maxAttempts) {\n throw new Error('Max attempts reached without matching predicate');\n }\n\n const delay = calculateDelay(\n attempts - 1,\n config.baseDelay ?? DEFAULT_CONFIG.baseDelay,\n config.maxDelay ?? DEFAULT_CONFIG.maxDelay,\n config.exponentialBackoff ?? DEFAULT_CONFIG.exponentialBackoff,\n config.jitter ?? DEFAULT_CONFIG.jitter,\n );\n\n await sleep(delay);\n } catch (error) {\n attempts++;\n\n if (attempts >= maxAttempts) {\n throw error;\n }\n\n const delay = calculateDelay(\n attempts - 1,\n config.baseDelay ?? DEFAULT_CONFIG.baseDelay,\n config.maxDelay ?? DEFAULT_CONFIG.maxDelay,\n config.exponentialBackoff ?? DEFAULT_CONFIG.exponentialBackoff,\n config.jitter ?? DEFAULT_CONFIG.jitter,\n );\n\n await sleep(delay);\n }\n }\n\n throw new Error('Max attempts reached');\n}\n\n/**\n * Exponential backoff iterator\n */\nexport class ExponentialBackoff implements AsyncIterable<number> {\n constructor(\n private baseDelay: number = 1000,\n private maxDelay: number = 30000,\n private maxAttempts: number = 10,\n private jitter: boolean = true,\n ) {}\n\n async *[Symbol.asyncIterator](): AsyncIterator<number> {\n for (let attempt = 0; attempt < this.maxAttempts; attempt++) {\n const delay = calculateDelay(attempt, this.baseDelay, this.maxDelay, true, this.jitter);\n\n yield delay;\n\n await sleep(delay);\n }\n }\n}\n\n/**\n * Retry policy builder\n */\nexport class RetryPolicyBuilder {\n private config: Partial<Required<RetryConfig>> = {};\n\n /**\n * Set max retries\n */\n maxRetries(count: number): this {\n this.config.maxRetries = count;\n return this;\n }\n\n /**\n * Set base delay\n */\n baseDelay(ms: number): this {\n this.config.baseDelay = ms;\n return this;\n }\n\n /**\n * Set max delay\n */\n maxDelay(ms: number): this {\n this.config.maxDelay = ms;\n return this;\n }\n\n /**\n * Enable/disable exponential backoff\n */\n exponentialBackoff(enabled: boolean = true): this {\n this.config.exponentialBackoff = enabled;\n return this;\n }\n\n /**\n * Enable/disable jitter\n */\n jitter(enabled: boolean = true): this {\n this.config.jitter = enabled;\n return this;\n }\n\n /**\n * Set custom retryable errors function\n */\n retryOn(fn: (error: Error) => boolean): this {\n this.config.retryableErrors = fn;\n return this;\n }\n\n /**\n * Set retry callback\n */\n onRetry(fn: (error: Error, attempt: number) => void): this {\n this.config.onRetry = fn;\n return this;\n }\n\n /**\n * Build retry config\n */\n build(): RetryConfig {\n return this.config;\n }\n\n /**\n * Execute function with built policy\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n return retry(fn, this.build());\n }\n}\n\n/**\n * Common retry policies\n */\nexport const RetryPolicies = {\n /**\n * Default policy - 3 retries with exponential backoff\n */\n default: (): RetryConfig => ({\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n exponentialBackoff: true,\n jitter: true,\n }),\n\n /**\n * Aggressive policy - more retries, faster backoff\n */\n aggressive: (): RetryConfig => ({\n maxRetries: 5,\n baseDelay: 500,\n maxDelay: 10000,\n exponentialBackoff: true,\n jitter: true,\n }),\n\n /**\n * Conservative policy - fewer retries, longer backoff\n */\n conservative: (): RetryConfig => ({\n maxRetries: 2,\n baseDelay: 2000,\n maxDelay: 60000,\n exponentialBackoff: true,\n jitter: true,\n }),\n\n /**\n * Linear backoff policy\n */\n linear: (): RetryConfig => ({\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 10000,\n exponentialBackoff: false,\n jitter: false,\n }),\n\n /**\n * Immediate retry policy - no delay\n */\n immediate: (): RetryConfig => ({\n maxRetries: 3,\n baseDelay: 0,\n maxDelay: 0,\n exponentialBackoff: false,\n jitter: false,\n }),\n\n /**\n * Network error only policy\n */\n networkOnly: (): RetryConfig => ({\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n exponentialBackoff: true,\n jitter: true,\n retryableErrors: (error) => error.name === 'NetworkError',\n }),\n\n /**\n * Idempotent operations policy (safe to retry)\n */\n idempotent: (): RetryConfig => ({\n maxRetries: 5,\n baseDelay: 1000,\n maxDelay: 30000,\n exponentialBackoff: true,\n jitter: true,\n }),\n};\n\n/**\n * Global retry configuration\n */\nclass GlobalRetryConfig {\n private config: RetryConfig = RetryPolicies.default();\n\n /**\n * Set global retry config\n */\n setConfig(config: RetryConfig): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Get global retry config\n */\n getConfig(): RetryConfig {\n return this.config;\n }\n\n /**\n * Reset to default config\n */\n reset(): void {\n this.config = RetryPolicies.default();\n }\n}\n\nexport const globalRetryConfig = new GlobalRetryConfig();\n"],"mappings":"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","names":["DEFAULT_CONFIG"]}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@revealui/resilience",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Resilience infrastructure for RevealUI - circuit breaker, retry, bulkhead patterns",
5
5
  "license": "MIT",
6
6
  "dependencies": {},
7
7
  "devDependencies": {
8
+ "@electric-sql/pglite": "^0.4.2",
8
9
  "@types/node": "^25.5.0",
9
10
  "tsup": "^8.5.1",
10
11
  "typescript": "^6.0.2",