@node-yalc/resilience 0.0.2 → 0.0.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.
@@ -1 +1 @@
1
- {"version":3,"file":"resilience.js","sourceRoot":"","sources":["../../../resilience/src/resilience.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resilience.js","sourceRoot":"","sources":["../../../resilience/src/resilience.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
- {
2
- "name": "@node-yalc/resilience",
3
- "version": "0.0.2",
4
- "main": "dist/index.js",
5
- "types": "dist/index.d.ts"
6
- }
1
+ {
2
+ "name": "@node-yalc/resilience",
3
+ "version": "0.0.3",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "type": "module"
7
+ }
package/src/resilience.ts CHANGED
@@ -1,5 +1,16 @@
1
+ /**
2
+ * Represents the current state of a Circuit Breaker.
3
+ * - `CLOSED`: Operations are permitted (normal operation).
4
+ * - `OPEN`: Operations are blocked because the failure threshold was exceeded.
5
+ * - `HALF_OPEN`: Circuit is testing the underlying service to see if it recovered.
6
+ */
1
7
  export type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
2
8
 
9
+ /**
10
+ * Enterprise Circuit Breaker pattern.
11
+ * Prevents catastrophic cascading failures by temporarily blocking execution of
12
+ * a degraded operation, giving the underlying service time to recover.
13
+ */
3
14
  export class CircuitBreaker {
4
15
  private failureThreshold: number;
5
16
  private recoveryTimeMs: number;
@@ -7,11 +18,26 @@ export class CircuitBreaker {
7
18
  private failureCount: number = 0;
8
19
  private lastFailureTime: number = 0;
9
20
 
21
+ /**
22
+ * Initializes the Circuit Breaker.
23
+ *
24
+ * @param failureThreshold The number of consecutive failures before the circuit trips (opens).
25
+ * @param recoveryTimeMs The duration in milliseconds to remain OPEN before shifting to HALF_OPEN.
26
+ */
10
27
  constructor(failureThreshold: number = 5, recoveryTimeMs: number = 10000) {
11
28
  this.failureThreshold = failureThreshold;
12
29
  this.recoveryTimeMs = recoveryTimeMs;
13
30
  }
14
31
 
32
+ /**
33
+ * Executes a potentially failing asynchronous function through the circuit breaker.
34
+ *
35
+ * @template T The expected return type of the wrapped function.
36
+ * @param {() => Promise<T>} fn The asynchronous operation to wrap.
37
+ * @param {() => T} [fallback] Optional synchronous fallback logic if the circuit is OPEN or fails.
38
+ * @returns {Promise<T>} The successful result of `fn` or `fallback`.
39
+ * @throws {Error} If execution fails and no fallback is provided, or if the circuit is OPEN.
40
+ */
15
41
  public async execute<T>(fn: () => Promise<T>, fallback?: () => T): Promise<T> {
16
42
  const now = Date.now();
17
43
 
@@ -37,6 +63,10 @@ export class CircuitBreaker {
37
63
  }
38
64
  }
39
65
 
66
+ /**
67
+ * Internal routine to increment failure metrics and trip the circuit if needed.
68
+ * @private
69
+ */
40
70
  private recordFailure(): void {
41
71
  this.failureCount++;
42
72
  this.lastFailureTime = Date.now();
@@ -45,22 +75,39 @@ export class CircuitBreaker {
45
75
  }
46
76
  }
47
77
 
78
+ /**
79
+ * Manually resets the circuit breaker back to its baseline CLOSED state.
80
+ */
48
81
  public reset(): void {
49
82
  this.state = 'CLOSED';
50
83
  this.failureCount = 0;
51
84
  }
52
85
 
86
+ /**
87
+ * Returns the current operational state of the circuit.
88
+ * @returns {CircuitState}
89
+ */
53
90
  public getState(): CircuitState {
54
91
  return this.state;
55
92
  }
56
93
  }
57
94
 
95
+ /**
96
+ * Enterprise Token Bucket Rate Limiter.
97
+ * Used to throttle API usage or heavy background jobs, preventing resource exhaustion.
98
+ */
58
99
  export class RateLimiter {
59
100
  private capacity: number;
60
101
  private refillRatePerSec: number;
61
102
  private tokens: number;
62
103
  private lastRefillTimestamp: number;
63
104
 
105
+ /**
106
+ * Initializes the Rate Limiter.
107
+ *
108
+ * @param capacity The maximum number of tokens the bucket can hold.
109
+ * @param refillRatePerSec The number of tokens added back to the bucket every second.
110
+ */
64
111
  constructor(capacity: number = 100, refillRatePerSec: number = 10) {
65
112
  this.capacity = capacity;
66
113
  this.refillRatePerSec = refillRatePerSec;
@@ -68,6 +115,12 @@ export class RateLimiter {
68
115
  this.lastRefillTimestamp = Date.now();
69
116
  }
70
117
 
118
+ /**
119
+ * Attempts to consume the specified number of tokens from the bucket.
120
+ *
121
+ * @param tokensRequested The number of tokens needed for the operation (default 1).
122
+ * @returns {boolean} True if the tokens were successfully consumed; false if rate limited.
123
+ */
71
124
  public allowRequest(tokensRequested: number = 1): boolean {
72
125
  this.refill();
73
126
  if (this.tokens >= tokensRequested) {
@@ -77,6 +130,10 @@ export class RateLimiter {
77
130
  return false;
78
131
  }
79
132
 
133
+ /**
134
+ * Internal routine that mathematically calculates and adds tokens based on elapsed time.
135
+ * @private
136
+ */
80
137
  private refill(): void {
81
138
  const now = Date.now();
82
139
  const elapsedSecs = (now - this.lastRefillTimestamp) / 1000;
@@ -85,9 +142,23 @@ export class RateLimiter {
85
142
  }
86
143
  }
87
144
 
145
+ /**
146
+ * Enterprise Singleflight (Promise Coalescing) Pattern.
147
+ * Prevents redundant concurrent executions of an identical heavy operation.
148
+ * If 10 requests ask for the same data simultaneously, only 1 function execution occurs
149
+ * and all 10 await the single shared promise.
150
+ */
88
151
  export class Singleflight {
89
152
  private inFlightCalls: Map<string, Promise<any>> = new Map();
90
153
 
154
+ /**
155
+ * Executes a deduplicated function call keyed by a unique string.
156
+ *
157
+ * @template T The expected return type.
158
+ * @param key A unique identifier representing the operation (e.g., 'getUser_123').
159
+ * @param fn The heavy asynchronous function to execute if no flight is already active.
160
+ * @returns {Promise<T>} The result of the operation.
161
+ */
91
162
  public async do<T>(key: string, fn: () => Promise<T>): Promise<T> {
92
163
  if (this.inFlightCalls.has(key)) {
93
164
  return this.inFlightCalls.get(key) as Promise<T>;