@revealui/resilience 0.2.1 → 0.2.3
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 +72 -1
- package/dist/index.js +114 -0
- package/dist/index.js.map +1 -1
- package/package.json +9 -3
- package/LICENSE.commercial +0 -111
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.
|
|
3
|
+
"version": "0.2.3",
|
|
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",
|
|
@@ -30,14 +31,19 @@
|
|
|
30
31
|
},
|
|
31
32
|
"type": "module",
|
|
32
33
|
"types": "./dist/index.d.ts",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/RevealUIStudio/revealui.git",
|
|
37
|
+
"directory": "packages/resilience"
|
|
38
|
+
},
|
|
33
39
|
"scripts": {
|
|
34
40
|
"build": "tsup",
|
|
35
41
|
"clean": "rm -rf dist",
|
|
36
42
|
"dev": "tsup --watch",
|
|
37
43
|
"lint": "biome check .",
|
|
38
44
|
"lint:fix": "biome check --write .",
|
|
39
|
-
"test": "vitest run
|
|
40
|
-
"test:coverage": "vitest run --coverage --coverage.reporter=json-summary --coverage.reporter=html --coverage.reporter=text
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:coverage": "vitest run --coverage --coverage.reporter=json-summary --coverage.reporter=html --coverage.reporter=text",
|
|
41
47
|
"test:watch": "vitest",
|
|
42
48
|
"typecheck": "tsc --noEmit"
|
|
43
49
|
}
|
package/LICENSE.commercial
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
RevealUI Commercial License
|
|
2
|
-
Version 1.0, February 2026
|
|
3
|
-
|
|
4
|
-
Copyright (c) 2025-2026 RevealUI Studio (founder@revealui.com)
|
|
5
|
-
|
|
6
|
-
TERMS AND CONDITIONS
|
|
7
|
-
|
|
8
|
-
1. DEFINITIONS
|
|
9
|
-
|
|
10
|
-
"Software" means the RevealUI source code, documentation, and associated
|
|
11
|
-
files contained in directories and packages designated as commercial,
|
|
12
|
-
including but not limited to: packages/ai, packages/harnesses, and any
|
|
13
|
-
directory named "ee" within the repository.
|
|
14
|
-
|
|
15
|
-
"License Key" means a valid RevealUI license key obtained through an active
|
|
16
|
-
paid subscription at https://revealui.com.
|
|
17
|
-
|
|
18
|
-
"Licensee" means the individual or organization that holds a valid License
|
|
19
|
-
Key through an active subscription.
|
|
20
|
-
|
|
21
|
-
"Production Use" means any use of the Software beyond local development and
|
|
22
|
-
evaluation, including but not limited to: deploying the Software to serve
|
|
23
|
-
end users, integrating the Software into a product or service, or using the
|
|
24
|
-
Software in a revenue-generating capacity.
|
|
25
|
-
|
|
26
|
-
2. GRANT OF RIGHTS
|
|
27
|
-
|
|
28
|
-
Subject to the terms of this License and a valid License Key, the Licensee
|
|
29
|
-
is granted a non-exclusive, non-transferable, revocable license to:
|
|
30
|
-
|
|
31
|
-
(a) Use the Software for internal development and Production Use.
|
|
32
|
-
(b) Modify the Software for internal use.
|
|
33
|
-
(c) Deploy the Software on infrastructure controlled by the Licensee.
|
|
34
|
-
|
|
35
|
-
Enterprise License holders are additionally granted the right to:
|
|
36
|
-
|
|
37
|
-
(d) Deploy the Software in a self-hosted environment.
|
|
38
|
-
(e) Remove or replace RevealUI branding (white-label).
|
|
39
|
-
(f) Use the Software for multiple tenants within the Licensee's
|
|
40
|
-
organization or customer base.
|
|
41
|
-
|
|
42
|
-
3. RESTRICTIONS
|
|
43
|
-
|
|
44
|
-
The Licensee SHALL NOT:
|
|
45
|
-
|
|
46
|
-
(a) Provide the Software, or any portion of it, to third parties as a
|
|
47
|
-
hosted or managed service that competes with RevealUI.
|
|
48
|
-
(b) Redistribute, sublicense, sell, or otherwise transfer the Software
|
|
49
|
-
or any portion of it to third parties.
|
|
50
|
-
(c) Remove, alter, or circumvent the license key verification
|
|
51
|
-
functionality of the Software.
|
|
52
|
-
(d) Use the Software in Production without a valid License Key.
|
|
53
|
-
(e) Share, publish, or make the License Key available to unauthorized
|
|
54
|
-
parties.
|
|
55
|
-
|
|
56
|
-
4. EVALUATION
|
|
57
|
-
|
|
58
|
-
The Software may be used for evaluation and local development purposes
|
|
59
|
-
without a License Key. Evaluation use does not grant any rights to
|
|
60
|
-
Production Use.
|
|
61
|
-
|
|
62
|
-
5. SUBSCRIPTION AND PAYMENT
|
|
63
|
-
|
|
64
|
-
This License is valid only during the term of an active paid subscription.
|
|
65
|
-
Upon cancellation or expiration of the subscription:
|
|
66
|
-
|
|
67
|
-
(a) The License terminates automatically.
|
|
68
|
-
(b) A grace period of fourteen (14) days is provided for the Licensee
|
|
69
|
-
to transition away from Production Use.
|
|
70
|
-
(c) After the grace period, the Licensee must cease all Production Use
|
|
71
|
-
of the Software.
|
|
72
|
-
|
|
73
|
-
6. INTELLECTUAL PROPERTY
|
|
74
|
-
|
|
75
|
-
The Software is and remains the intellectual property of RevealUI Studio.
|
|
76
|
-
This License does not grant any ownership rights. Contributions to
|
|
77
|
-
commercial portions of the Software require a Contributor License Agreement.
|
|
78
|
-
|
|
79
|
-
7. OPEN SOURCE COMPONENTS
|
|
80
|
-
|
|
81
|
-
This License applies only to files and directories designated as commercial.
|
|
82
|
-
Files under the MIT License (as indicated in the root LICENSE file) are not
|
|
83
|
-
subject to this commercial license and may be used freely under MIT terms.
|
|
84
|
-
|
|
85
|
-
8. DISCLAIMER OF WARRANTY
|
|
86
|
-
|
|
87
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
88
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
89
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
90
|
-
|
|
91
|
-
9. LIMITATION OF LIABILITY
|
|
92
|
-
|
|
93
|
-
IN NO EVENT SHALL REVEALUI STUDIO BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
94
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
95
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
96
|
-
DEALINGS IN THE SOFTWARE, EXCEEDING THE AMOUNT PAID BY THE LICENSEE IN
|
|
97
|
-
THE TWELVE (12) MONTHS PRECEDING THE CLAIM.
|
|
98
|
-
|
|
99
|
-
10. GOVERNING LAW
|
|
100
|
-
|
|
101
|
-
This License shall be governed by the laws of the State of California,
|
|
102
|
-
United States of America, without regard to its conflict of law provisions.
|
|
103
|
-
|
|
104
|
-
11. ENTIRE AGREEMENT
|
|
105
|
-
|
|
106
|
-
This License constitutes the entire agreement between the parties with
|
|
107
|
-
respect to the commercial portions of the Software and supersedes all
|
|
108
|
-
prior agreements, understandings, and communications.
|
|
109
|
-
|
|
110
|
-
For licensing inquiries: founder@revealui.com
|
|
111
|
-
For pricing and subscriptions: https://revealui.com/pricing
|