@hazeljs/resilience 0.2.0-beta.41
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/LICENSE +192 -0
- package/README.md +95 -0
- package/dist/__tests__/bulkhead-timeout.test.d.ts +2 -0
- package/dist/__tests__/bulkhead-timeout.test.d.ts.map +1 -0
- package/dist/__tests__/bulkhead-timeout.test.js +74 -0
- package/dist/__tests__/circuit-breaker.test.d.ts +2 -0
- package/dist/__tests__/circuit-breaker.test.d.ts.map +1 -0
- package/dist/__tests__/circuit-breaker.test.js +160 -0
- package/dist/__tests__/decorators.test.d.ts +2 -0
- package/dist/__tests__/decorators.test.d.ts.map +1 -0
- package/dist/__tests__/decorators.test.js +288 -0
- package/dist/__tests__/index.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts.map +1 -0
- package/dist/__tests__/index.test.js +50 -0
- package/dist/__tests__/metrics.test.d.ts +2 -0
- package/dist/__tests__/metrics.test.d.ts.map +1 -0
- package/dist/__tests__/metrics.test.js +83 -0
- package/dist/__tests__/rate-limiter.test.d.ts +2 -0
- package/dist/__tests__/rate-limiter.test.d.ts.map +1 -0
- package/dist/__tests__/rate-limiter.test.js +143 -0
- package/dist/__tests__/retry-policy.test.d.ts +2 -0
- package/dist/__tests__/retry-policy.test.d.ts.map +1 -0
- package/dist/__tests__/retry-policy.test.js +84 -0
- package/dist/__tests__/sliding-window.test.d.ts +2 -0
- package/dist/__tests__/sliding-window.test.d.ts.map +1 -0
- package/dist/__tests__/sliding-window.test.js +93 -0
- package/dist/bulkhead/bulkhead.d.ts +34 -0
- package/dist/bulkhead/bulkhead.d.ts.map +1 -0
- package/dist/bulkhead/bulkhead.js +97 -0
- package/dist/circuit-breaker/circuit-breaker-registry.d.ts +38 -0
- package/dist/circuit-breaker/circuit-breaker-registry.d.ts.map +1 -0
- package/dist/circuit-breaker/circuit-breaker-registry.js +61 -0
- package/dist/circuit-breaker/circuit-breaker.d.ts +51 -0
- package/dist/circuit-breaker/circuit-breaker.d.ts.map +1 -0
- package/dist/circuit-breaker/circuit-breaker.js +182 -0
- package/dist/circuit-breaker/sliding-window.d.ts +49 -0
- package/dist/circuit-breaker/sliding-window.d.ts.map +1 -0
- package/dist/circuit-breaker/sliding-window.js +89 -0
- package/dist/decorators/index.d.ts +51 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +133 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/metrics/metrics-collector.d.ts +69 -0
- package/dist/metrics/metrics-collector.d.ts.map +1 -0
- package/dist/metrics/metrics-collector.js +180 -0
- package/dist/rate-limiter/rate-limiter.d.ts +72 -0
- package/dist/rate-limiter/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter/rate-limiter.js +147 -0
- package/dist/retry/retry-policy.d.ts +19 -0
- package/dist/retry/retry-policy.d.ts.map +1 -0
- package/dist/retry/retry-policy.js +87 -0
- package/dist/timeout/timeout.d.ts +23 -0
- package/dist/timeout/timeout.d.ts.map +1 -0
- package/dist/timeout/timeout.js +55 -0
- package/dist/types/index.d.ts +135 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +61 -0
- package/package.json +63 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sliding Window implementations for Circuit Breaker
|
|
4
|
+
*
|
|
5
|
+
* Count-based: tracks the last N calls
|
|
6
|
+
* Time-based: tracks calls within a rolling time window
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.TimeBasedSlidingWindow = exports.CountBasedSlidingWindow = void 0;
|
|
10
|
+
exports.createSlidingWindow = createSlidingWindow;
|
|
11
|
+
/**
|
|
12
|
+
* Count-based sliding window
|
|
13
|
+
* Tracks the last `size` calls regardless of time
|
|
14
|
+
*/
|
|
15
|
+
class CountBasedSlidingWindow {
|
|
16
|
+
constructor(size) {
|
|
17
|
+
this.size = size;
|
|
18
|
+
this.entries = [];
|
|
19
|
+
}
|
|
20
|
+
record(success) {
|
|
21
|
+
this.entries.push(success);
|
|
22
|
+
if (this.entries.length > this.size) {
|
|
23
|
+
this.entries.shift();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
getResult() {
|
|
27
|
+
const total = this.entries.length;
|
|
28
|
+
if (total === 0) {
|
|
29
|
+
return { totalCalls: 0, failureCount: 0, failureRate: 0 };
|
|
30
|
+
}
|
|
31
|
+
const failures = this.entries.filter((s) => !s).length;
|
|
32
|
+
return {
|
|
33
|
+
totalCalls: total,
|
|
34
|
+
failureCount: failures,
|
|
35
|
+
failureRate: (failures / total) * 100,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
reset() {
|
|
39
|
+
this.entries = [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.CountBasedSlidingWindow = CountBasedSlidingWindow;
|
|
43
|
+
/**
|
|
44
|
+
* Time-based sliding window
|
|
45
|
+
* Tracks calls within a rolling time window of `sizeMs` milliseconds
|
|
46
|
+
*/
|
|
47
|
+
class TimeBasedSlidingWindow {
|
|
48
|
+
constructor(sizeMs) {
|
|
49
|
+
this.sizeMs = sizeMs;
|
|
50
|
+
this.entries = [];
|
|
51
|
+
}
|
|
52
|
+
record(success) {
|
|
53
|
+
this.entries.push({ timestamp: Date.now(), success });
|
|
54
|
+
this.evict();
|
|
55
|
+
}
|
|
56
|
+
getResult() {
|
|
57
|
+
this.evict();
|
|
58
|
+
const total = this.entries.length;
|
|
59
|
+
if (total === 0) {
|
|
60
|
+
return { totalCalls: 0, failureCount: 0, failureRate: 0 };
|
|
61
|
+
}
|
|
62
|
+
const failures = this.entries.filter((e) => !e.success).length;
|
|
63
|
+
return {
|
|
64
|
+
totalCalls: total,
|
|
65
|
+
failureCount: failures,
|
|
66
|
+
failureRate: (failures / total) * 100,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
reset() {
|
|
70
|
+
this.entries = [];
|
|
71
|
+
}
|
|
72
|
+
evict() {
|
|
73
|
+
const cutoff = Date.now() - this.sizeMs;
|
|
74
|
+
let i = 0;
|
|
75
|
+
while (i < this.entries.length && this.entries[i].timestamp < cutoff) {
|
|
76
|
+
i++;
|
|
77
|
+
}
|
|
78
|
+
if (i > 0) {
|
|
79
|
+
this.entries = this.entries.slice(i);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.TimeBasedSlidingWindow = TimeBasedSlidingWindow;
|
|
84
|
+
/**
|
|
85
|
+
* Factory to create the appropriate sliding window
|
|
86
|
+
*/
|
|
87
|
+
function createSlidingWindow(type, size) {
|
|
88
|
+
return type === 'count' ? new CountBasedSlidingWindow(size) : new TimeBasedSlidingWindow(size);
|
|
89
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resilience Decorators
|
|
3
|
+
* Decorator-based API consistent with HazelJS philosophy.
|
|
4
|
+
*
|
|
5
|
+
* Decorators compose in the order they are declared (outermost first).
|
|
6
|
+
* Example:
|
|
7
|
+
* @CircuitBreaker(...) <-- outermost wrapper
|
|
8
|
+
* @Retry(...) <-- wraps the timeout
|
|
9
|
+
* @Timeout(5000) <-- wraps the bulkhead
|
|
10
|
+
* @Bulkhead(...) <-- innermost wrapper around the original fn
|
|
11
|
+
*/
|
|
12
|
+
import 'reflect-metadata';
|
|
13
|
+
import { CircuitBreakerConfig, RetryConfig, BulkheadConfig, RateLimiterConfig } from '../types';
|
|
14
|
+
/**
|
|
15
|
+
* @CircuitBreaker decorator
|
|
16
|
+
* Wraps a method with circuit breaker protection.
|
|
17
|
+
*/
|
|
18
|
+
export declare function CircuitBreaker(config?: Partial<CircuitBreakerConfig>): MethodDecorator;
|
|
19
|
+
/**
|
|
20
|
+
* @Retry decorator
|
|
21
|
+
* Wraps a method with retry logic.
|
|
22
|
+
*/
|
|
23
|
+
export declare function Retry(config?: Partial<RetryConfig>): MethodDecorator;
|
|
24
|
+
/**
|
|
25
|
+
* @Timeout decorator
|
|
26
|
+
* Wraps a method with a timeout.
|
|
27
|
+
*/
|
|
28
|
+
export declare function Timeout(durationOrConfig: number | {
|
|
29
|
+
duration: number;
|
|
30
|
+
message?: string;
|
|
31
|
+
}): MethodDecorator;
|
|
32
|
+
/**
|
|
33
|
+
* @Bulkhead decorator
|
|
34
|
+
* Limits concurrent executions of a method.
|
|
35
|
+
*/
|
|
36
|
+
export declare function Bulkhead(config: BulkheadConfig): MethodDecorator;
|
|
37
|
+
/**
|
|
38
|
+
* @Fallback decorator
|
|
39
|
+
* Marks a method as the fallback for a specified primary method.
|
|
40
|
+
*
|
|
41
|
+
* Usage:
|
|
42
|
+
* @Fallback('processPayment')
|
|
43
|
+
* async processPaymentFallback(...) { }
|
|
44
|
+
*/
|
|
45
|
+
export declare function Fallback(primaryMethodName: string): MethodDecorator;
|
|
46
|
+
/**
|
|
47
|
+
* @RateLimit decorator
|
|
48
|
+
* Rate limits a method.
|
|
49
|
+
*/
|
|
50
|
+
export declare function RateLimit(config: RateLimiterConfig): MethodDecorator;
|
|
51
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,kBAAkB,CAAC;AAM1B,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAKhG;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,eAAe,CAyCtF;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,eAAe,CAWpE;AAED;;;GAGG;AACH,wBAAgB,OAAO,CACrB,gBAAgB,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,eAAe,CAajB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,CAWhE;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,eAAe,CAMnE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAWpE"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Resilience Decorators
|
|
4
|
+
* Decorator-based API consistent with HazelJS philosophy.
|
|
5
|
+
*
|
|
6
|
+
* Decorators compose in the order they are declared (outermost first).
|
|
7
|
+
* Example:
|
|
8
|
+
* @CircuitBreaker(...) <-- outermost wrapper
|
|
9
|
+
* @Retry(...) <-- wraps the timeout
|
|
10
|
+
* @Timeout(5000) <-- wraps the bulkhead
|
|
11
|
+
* @Bulkhead(...) <-- innermost wrapper around the original fn
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.CircuitBreaker = CircuitBreaker;
|
|
15
|
+
exports.Retry = Retry;
|
|
16
|
+
exports.Timeout = Timeout;
|
|
17
|
+
exports.Bulkhead = Bulkhead;
|
|
18
|
+
exports.Fallback = Fallback;
|
|
19
|
+
exports.RateLimit = RateLimit;
|
|
20
|
+
require("reflect-metadata");
|
|
21
|
+
const circuit_breaker_registry_1 = require("../circuit-breaker/circuit-breaker-registry");
|
|
22
|
+
const retry_policy_1 = require("../retry/retry-policy");
|
|
23
|
+
const timeout_1 = require("../timeout/timeout");
|
|
24
|
+
const bulkhead_1 = require("../bulkhead/bulkhead");
|
|
25
|
+
const rate_limiter_1 = require("../rate-limiter/rate-limiter");
|
|
26
|
+
// Metadata keys
|
|
27
|
+
const FALLBACK_KEY = Symbol('resilience:fallback');
|
|
28
|
+
/**
|
|
29
|
+
* @CircuitBreaker decorator
|
|
30
|
+
* Wraps a method with circuit breaker protection.
|
|
31
|
+
*/
|
|
32
|
+
function CircuitBreaker(config) {
|
|
33
|
+
return function (target, propertyKey, descriptor) {
|
|
34
|
+
const originalMethod = descriptor.value;
|
|
35
|
+
const breakerName = `${target.constructor.name}.${String(propertyKey)}`;
|
|
36
|
+
descriptor.value = async function (...args) {
|
|
37
|
+
const breaker = circuit_breaker_registry_1.CircuitBreakerRegistry.getOrCreate(breakerName, config);
|
|
38
|
+
try {
|
|
39
|
+
return await breaker.execute(() => originalMethod.apply(this, args));
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
// If there's a fallback configured, try it
|
|
43
|
+
if (config?.fallback) {
|
|
44
|
+
const fallbackMethod = this[config.fallback];
|
|
45
|
+
if (typeof fallbackMethod === 'function') {
|
|
46
|
+
return fallbackMethod.apply(this, args);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Check for decorator-based fallback
|
|
50
|
+
const fallbackName = Reflect.getMetadata(FALLBACK_KEY, target, propertyKey);
|
|
51
|
+
if (fallbackName) {
|
|
52
|
+
const fallbackMethod = this[fallbackName];
|
|
53
|
+
if (typeof fallbackMethod === 'function') {
|
|
54
|
+
return fallbackMethod.apply(this, args);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
return descriptor;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* @Retry decorator
|
|
65
|
+
* Wraps a method with retry logic.
|
|
66
|
+
*/
|
|
67
|
+
function Retry(config) {
|
|
68
|
+
return function (_target, _propertyKey, descriptor) {
|
|
69
|
+
const originalMethod = descriptor.value;
|
|
70
|
+
const retryPolicy = new retry_policy_1.RetryPolicy(config);
|
|
71
|
+
descriptor.value = async function (...args) {
|
|
72
|
+
return retryPolicy.execute(() => originalMethod.apply(this, args));
|
|
73
|
+
};
|
|
74
|
+
return descriptor;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @Timeout decorator
|
|
79
|
+
* Wraps a method with a timeout.
|
|
80
|
+
*/
|
|
81
|
+
function Timeout(durationOrConfig) {
|
|
82
|
+
return function (_target, _propertyKey, descriptor) {
|
|
83
|
+
const originalMethod = descriptor.value;
|
|
84
|
+
const timeout = new timeout_1.Timeout(typeof durationOrConfig === 'number' ? durationOrConfig : durationOrConfig);
|
|
85
|
+
descriptor.value = async function (...args) {
|
|
86
|
+
return timeout.execute(() => originalMethod.apply(this, args));
|
|
87
|
+
};
|
|
88
|
+
return descriptor;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* @Bulkhead decorator
|
|
93
|
+
* Limits concurrent executions of a method.
|
|
94
|
+
*/
|
|
95
|
+
function Bulkhead(config) {
|
|
96
|
+
return function (_target, _propertyKey, descriptor) {
|
|
97
|
+
const originalMethod = descriptor.value;
|
|
98
|
+
const bulkhead = new bulkhead_1.Bulkhead(config);
|
|
99
|
+
descriptor.value = async function (...args) {
|
|
100
|
+
return bulkhead.execute(() => originalMethod.apply(this, args));
|
|
101
|
+
};
|
|
102
|
+
return descriptor;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* @Fallback decorator
|
|
107
|
+
* Marks a method as the fallback for a specified primary method.
|
|
108
|
+
*
|
|
109
|
+
* Usage:
|
|
110
|
+
* @Fallback('processPayment')
|
|
111
|
+
* async processPaymentFallback(...) { }
|
|
112
|
+
*/
|
|
113
|
+
function Fallback(primaryMethodName) {
|
|
114
|
+
return function (target, propertyKey, descriptor) {
|
|
115
|
+
// Store the fallback mapping on the primary method
|
|
116
|
+
Reflect.defineMetadata(FALLBACK_KEY, String(propertyKey), target, primaryMethodName);
|
|
117
|
+
return descriptor;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* @RateLimit decorator
|
|
122
|
+
* Rate limits a method.
|
|
123
|
+
*/
|
|
124
|
+
function RateLimit(config) {
|
|
125
|
+
return function (_target, _propertyKey, descriptor) {
|
|
126
|
+
const originalMethod = descriptor.value;
|
|
127
|
+
const limiter = new rate_limiter_1.RateLimiter(config);
|
|
128
|
+
descriptor.value = async function (...args) {
|
|
129
|
+
return limiter.execute(() => originalMethod.apply(this, args));
|
|
130
|
+
};
|
|
131
|
+
return descriptor;
|
|
132
|
+
};
|
|
133
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hazeljs/resilience
|
|
3
|
+
* Fault-tolerance and resilience patterns for HazelJS
|
|
4
|
+
*
|
|
5
|
+
* Provides circuit breaker, retry, timeout, bulkhead, rate limiter,
|
|
6
|
+
* and metrics collection — all usable via decorators or programmatic API.
|
|
7
|
+
*/
|
|
8
|
+
export { CircuitState, CircuitBreakerConfig, CircuitBreakerMetrics, CircuitBreakerError, SlidingWindowConfig, RetryConfig, BackoffStrategy, RetryExhaustedError, TimeoutConfig, TimeoutError, BulkheadConfig, BulkheadMetrics, BulkheadError, RateLimiterConfig, RateLimiterStrategy, RateLimitError, MetricsSnapshot, MetricsEntry, ResilienceError, } from './types';
|
|
9
|
+
export { CircuitBreaker } from './circuit-breaker/circuit-breaker';
|
|
10
|
+
export { CircuitBreakerRegistry } from './circuit-breaker/circuit-breaker-registry';
|
|
11
|
+
export { SlidingWindow, CountBasedSlidingWindow, TimeBasedSlidingWindow, createSlidingWindow, } from './circuit-breaker/sliding-window';
|
|
12
|
+
export { RetryPolicy } from './retry/retry-policy';
|
|
13
|
+
export { Timeout, withTimeout } from './timeout/timeout';
|
|
14
|
+
export { Bulkhead } from './bulkhead/bulkhead';
|
|
15
|
+
export { RateLimiter, TokenBucketLimiter, SlidingWindowLimiter } from './rate-limiter/rate-limiter';
|
|
16
|
+
export { MetricsCollector, MetricsRegistry } from './metrics/metrics-collector';
|
|
17
|
+
export { CircuitBreaker as WithCircuitBreaker, Retry as WithRetry, Timeout as WithTimeout, Bulkhead as WithBulkhead, Fallback, RateLimit as WithRateLimit, } from './decorators';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,YAAY,EACZ,eAAe,GAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGpG,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGhF,OAAO,EACL,cAAc,IAAI,kBAAkB,EACpC,KAAK,IAAI,SAAS,EAClB,OAAO,IAAI,WAAW,EACtB,QAAQ,IAAI,YAAY,EACxB,QAAQ,EACR,SAAS,IAAI,aAAa,GAC3B,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @hazeljs/resilience
|
|
4
|
+
* Fault-tolerance and resilience patterns for HazelJS
|
|
5
|
+
*
|
|
6
|
+
* Provides circuit breaker, retry, timeout, bulkhead, rate limiter,
|
|
7
|
+
* and metrics collection — all usable via decorators or programmatic API.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.WithRateLimit = exports.Fallback = exports.WithBulkhead = exports.WithTimeout = exports.WithRetry = exports.WithCircuitBreaker = exports.MetricsRegistry = exports.MetricsCollector = exports.SlidingWindowLimiter = exports.TokenBucketLimiter = exports.RateLimiter = exports.Bulkhead = exports.withTimeout = exports.Timeout = exports.RetryPolicy = exports.createSlidingWindow = exports.TimeBasedSlidingWindow = exports.CountBasedSlidingWindow = exports.CircuitBreakerRegistry = exports.CircuitBreaker = exports.ResilienceError = exports.RateLimitError = exports.BulkheadError = exports.TimeoutError = exports.RetryExhaustedError = exports.CircuitBreakerError = exports.CircuitState = void 0;
|
|
11
|
+
// Types & Errors
|
|
12
|
+
var types_1 = require("./types");
|
|
13
|
+
Object.defineProperty(exports, "CircuitState", { enumerable: true, get: function () { return types_1.CircuitState; } });
|
|
14
|
+
Object.defineProperty(exports, "CircuitBreakerError", { enumerable: true, get: function () { return types_1.CircuitBreakerError; } });
|
|
15
|
+
Object.defineProperty(exports, "RetryExhaustedError", { enumerable: true, get: function () { return types_1.RetryExhaustedError; } });
|
|
16
|
+
Object.defineProperty(exports, "TimeoutError", { enumerable: true, get: function () { return types_1.TimeoutError; } });
|
|
17
|
+
Object.defineProperty(exports, "BulkheadError", { enumerable: true, get: function () { return types_1.BulkheadError; } });
|
|
18
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return types_1.RateLimitError; } });
|
|
19
|
+
Object.defineProperty(exports, "ResilienceError", { enumerable: true, get: function () { return types_1.ResilienceError; } });
|
|
20
|
+
// Circuit Breaker
|
|
21
|
+
var circuit_breaker_1 = require("./circuit-breaker/circuit-breaker");
|
|
22
|
+
Object.defineProperty(exports, "CircuitBreaker", { enumerable: true, get: function () { return circuit_breaker_1.CircuitBreaker; } });
|
|
23
|
+
var circuit_breaker_registry_1 = require("./circuit-breaker/circuit-breaker-registry");
|
|
24
|
+
Object.defineProperty(exports, "CircuitBreakerRegistry", { enumerable: true, get: function () { return circuit_breaker_registry_1.CircuitBreakerRegistry; } });
|
|
25
|
+
var sliding_window_1 = require("./circuit-breaker/sliding-window");
|
|
26
|
+
Object.defineProperty(exports, "CountBasedSlidingWindow", { enumerable: true, get: function () { return sliding_window_1.CountBasedSlidingWindow; } });
|
|
27
|
+
Object.defineProperty(exports, "TimeBasedSlidingWindow", { enumerable: true, get: function () { return sliding_window_1.TimeBasedSlidingWindow; } });
|
|
28
|
+
Object.defineProperty(exports, "createSlidingWindow", { enumerable: true, get: function () { return sliding_window_1.createSlidingWindow; } });
|
|
29
|
+
// Retry
|
|
30
|
+
var retry_policy_1 = require("./retry/retry-policy");
|
|
31
|
+
Object.defineProperty(exports, "RetryPolicy", { enumerable: true, get: function () { return retry_policy_1.RetryPolicy; } });
|
|
32
|
+
// Timeout
|
|
33
|
+
var timeout_1 = require("./timeout/timeout");
|
|
34
|
+
Object.defineProperty(exports, "Timeout", { enumerable: true, get: function () { return timeout_1.Timeout; } });
|
|
35
|
+
Object.defineProperty(exports, "withTimeout", { enumerable: true, get: function () { return timeout_1.withTimeout; } });
|
|
36
|
+
// Bulkhead
|
|
37
|
+
var bulkhead_1 = require("./bulkhead/bulkhead");
|
|
38
|
+
Object.defineProperty(exports, "Bulkhead", { enumerable: true, get: function () { return bulkhead_1.Bulkhead; } });
|
|
39
|
+
// Rate Limiter
|
|
40
|
+
var rate_limiter_1 = require("./rate-limiter/rate-limiter");
|
|
41
|
+
Object.defineProperty(exports, "RateLimiter", { enumerable: true, get: function () { return rate_limiter_1.RateLimiter; } });
|
|
42
|
+
Object.defineProperty(exports, "TokenBucketLimiter", { enumerable: true, get: function () { return rate_limiter_1.TokenBucketLimiter; } });
|
|
43
|
+
Object.defineProperty(exports, "SlidingWindowLimiter", { enumerable: true, get: function () { return rate_limiter_1.SlidingWindowLimiter; } });
|
|
44
|
+
// Metrics
|
|
45
|
+
var metrics_collector_1 = require("./metrics/metrics-collector");
|
|
46
|
+
Object.defineProperty(exports, "MetricsCollector", { enumerable: true, get: function () { return metrics_collector_1.MetricsCollector; } });
|
|
47
|
+
Object.defineProperty(exports, "MetricsRegistry", { enumerable: true, get: function () { return metrics_collector_1.MetricsRegistry; } });
|
|
48
|
+
// Decorators (re-exported with decorator-friendly names)
|
|
49
|
+
var decorators_1 = require("./decorators");
|
|
50
|
+
Object.defineProperty(exports, "WithCircuitBreaker", { enumerable: true, get: function () { return decorators_1.CircuitBreaker; } });
|
|
51
|
+
Object.defineProperty(exports, "WithRetry", { enumerable: true, get: function () { return decorators_1.Retry; } });
|
|
52
|
+
Object.defineProperty(exports, "WithTimeout", { enumerable: true, get: function () { return decorators_1.Timeout; } });
|
|
53
|
+
Object.defineProperty(exports, "WithBulkhead", { enumerable: true, get: function () { return decorators_1.Bulkhead; } });
|
|
54
|
+
Object.defineProperty(exports, "Fallback", { enumerable: true, get: function () { return decorators_1.Fallback; } });
|
|
55
|
+
Object.defineProperty(exports, "WithRateLimit", { enumerable: true, get: function () { return decorators_1.RateLimit; } });
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics Collector
|
|
3
|
+
* Tracks success/failure/latency per target. Used internally by circuit breakers
|
|
4
|
+
* and exposed to the gateway for canary deployment decisions.
|
|
5
|
+
*/
|
|
6
|
+
import { MetricsSnapshot } from '../types';
|
|
7
|
+
export declare class MetricsCollector {
|
|
8
|
+
private entries;
|
|
9
|
+
private windowMs;
|
|
10
|
+
constructor(windowMs?: number);
|
|
11
|
+
/**
|
|
12
|
+
* Record a successful call
|
|
13
|
+
*/
|
|
14
|
+
recordSuccess(duration: number): void;
|
|
15
|
+
/**
|
|
16
|
+
* Record a failed call
|
|
17
|
+
*/
|
|
18
|
+
recordFailure(duration: number, error?: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Get a snapshot of current metrics within the sliding window
|
|
21
|
+
*/
|
|
22
|
+
getSnapshot(): MetricsSnapshot;
|
|
23
|
+
/**
|
|
24
|
+
* Get the current failure rate as a percentage (0-100)
|
|
25
|
+
*/
|
|
26
|
+
getFailureRate(): number;
|
|
27
|
+
/**
|
|
28
|
+
* Get the number of entries in the current window
|
|
29
|
+
*/
|
|
30
|
+
getCallCount(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Get failure count in the current window
|
|
33
|
+
*/
|
|
34
|
+
getFailureCount(): number;
|
|
35
|
+
/**
|
|
36
|
+
* Get success count in the current window
|
|
37
|
+
*/
|
|
38
|
+
getSuccessCount(): number;
|
|
39
|
+
/**
|
|
40
|
+
* Reset all metrics
|
|
41
|
+
*/
|
|
42
|
+
reset(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Set the window duration
|
|
45
|
+
*/
|
|
46
|
+
setWindow(windowMs: number): void;
|
|
47
|
+
/**
|
|
48
|
+
* Evict entries outside the sliding window
|
|
49
|
+
*/
|
|
50
|
+
private evict;
|
|
51
|
+
/**
|
|
52
|
+
* Calculate percentile from sorted array
|
|
53
|
+
*/
|
|
54
|
+
private percentile;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Global registry of metrics collectors, keyed by name
|
|
58
|
+
*/
|
|
59
|
+
export declare class MetricsRegistry {
|
|
60
|
+
private static collectors;
|
|
61
|
+
static getOrCreate(name: string, windowMs?: number): MetricsCollector;
|
|
62
|
+
static get(name: string): MetricsCollector | undefined;
|
|
63
|
+
static getAll(): Map<string, MetricsCollector>;
|
|
64
|
+
static remove(name: string): boolean;
|
|
65
|
+
static clear(): void;
|
|
66
|
+
static getSnapshot(name: string): MetricsSnapshot | undefined;
|
|
67
|
+
static getAllSnapshots(): Record<string, MetricsSnapshot>;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=metrics-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-collector.d.ts","sourceRoot":"","sources":["../../src/metrics/metrics-collector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAgB,eAAe,EAAE,MAAM,UAAU,CAAC;AAEzD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,GAAE,MAAe;IAIrC;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IASrC;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAUrD;;OAEG;IACH,WAAW,IAAI,eAAe;IAuC9B;;OAEG;IACH,cAAc,IAAI,MAAM;IAOxB;;OAEG;IACH,YAAY,IAAI,MAAM;IAKtB;;OAEG;IACH,eAAe,IAAI,MAAM;IAKzB;;OAEG;IACH,eAAe,IAAI,MAAM;IAKzB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKjC;;OAEG;IACH,OAAO,CAAC,KAAK;IAYb;;OAEG;IACH,OAAO,CAAC,UAAU;CAKnB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAuC;IAEhE,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB;IASrE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAItD,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAI9C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIpC,MAAM,CAAC,KAAK,IAAI,IAAI;IAIpB,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAI7D,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;CAO1D"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Metrics Collector
|
|
4
|
+
* Tracks success/failure/latency per target. Used internally by circuit breakers
|
|
5
|
+
* and exposed to the gateway for canary deployment decisions.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.MetricsRegistry = exports.MetricsCollector = void 0;
|
|
9
|
+
class MetricsCollector {
|
|
10
|
+
constructor(windowMs = 60000) {
|
|
11
|
+
this.entries = [];
|
|
12
|
+
this.windowMs = windowMs;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Record a successful call
|
|
16
|
+
*/
|
|
17
|
+
recordSuccess(duration) {
|
|
18
|
+
this.entries.push({
|
|
19
|
+
timestamp: Date.now(),
|
|
20
|
+
duration,
|
|
21
|
+
success: true,
|
|
22
|
+
});
|
|
23
|
+
this.evict();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Record a failed call
|
|
27
|
+
*/
|
|
28
|
+
recordFailure(duration, error) {
|
|
29
|
+
this.entries.push({
|
|
30
|
+
timestamp: Date.now(),
|
|
31
|
+
duration,
|
|
32
|
+
success: false,
|
|
33
|
+
error,
|
|
34
|
+
});
|
|
35
|
+
this.evict();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get a snapshot of current metrics within the sliding window
|
|
39
|
+
*/
|
|
40
|
+
getSnapshot() {
|
|
41
|
+
this.evict();
|
|
42
|
+
const entries = this.entries;
|
|
43
|
+
const total = entries.length;
|
|
44
|
+
if (total === 0) {
|
|
45
|
+
return {
|
|
46
|
+
totalCalls: 0,
|
|
47
|
+
successCalls: 0,
|
|
48
|
+
failureCalls: 0,
|
|
49
|
+
failureRate: 0,
|
|
50
|
+
averageResponseTime: 0,
|
|
51
|
+
p50ResponseTime: 0,
|
|
52
|
+
p95ResponseTime: 0,
|
|
53
|
+
p99ResponseTime: 0,
|
|
54
|
+
minResponseTime: 0,
|
|
55
|
+
maxResponseTime: 0,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const successes = entries.filter((e) => e.success).length;
|
|
59
|
+
const failures = total - successes;
|
|
60
|
+
const durations = entries.map((e) => e.duration).sort((a, b) => a - b);
|
|
61
|
+
return {
|
|
62
|
+
totalCalls: total,
|
|
63
|
+
successCalls: successes,
|
|
64
|
+
failureCalls: failures,
|
|
65
|
+
failureRate: total > 0 ? (failures / total) * 100 : 0,
|
|
66
|
+
averageResponseTime: durations.reduce((a, b) => a + b, 0) / total,
|
|
67
|
+
p50ResponseTime: this.percentile(durations, 50),
|
|
68
|
+
p95ResponseTime: this.percentile(durations, 95),
|
|
69
|
+
p99ResponseTime: this.percentile(durations, 99),
|
|
70
|
+
minResponseTime: durations[0],
|
|
71
|
+
maxResponseTime: durations[durations.length - 1],
|
|
72
|
+
lastCallTime: entries[entries.length - 1]?.timestamp,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get the current failure rate as a percentage (0-100)
|
|
77
|
+
*/
|
|
78
|
+
getFailureRate() {
|
|
79
|
+
this.evict();
|
|
80
|
+
if (this.entries.length === 0)
|
|
81
|
+
return 0;
|
|
82
|
+
const failures = this.entries.filter((e) => !e.success).length;
|
|
83
|
+
return (failures / this.entries.length) * 100;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get the number of entries in the current window
|
|
87
|
+
*/
|
|
88
|
+
getCallCount() {
|
|
89
|
+
this.evict();
|
|
90
|
+
return this.entries.length;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get failure count in the current window
|
|
94
|
+
*/
|
|
95
|
+
getFailureCount() {
|
|
96
|
+
this.evict();
|
|
97
|
+
return this.entries.filter((e) => !e.success).length;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get success count in the current window
|
|
101
|
+
*/
|
|
102
|
+
getSuccessCount() {
|
|
103
|
+
this.evict();
|
|
104
|
+
return this.entries.filter((e) => e.success).length;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Reset all metrics
|
|
108
|
+
*/
|
|
109
|
+
reset() {
|
|
110
|
+
this.entries = [];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Set the window duration
|
|
114
|
+
*/
|
|
115
|
+
setWindow(windowMs) {
|
|
116
|
+
this.windowMs = windowMs;
|
|
117
|
+
this.evict();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Evict entries outside the sliding window
|
|
121
|
+
*/
|
|
122
|
+
evict() {
|
|
123
|
+
const cutoff = Date.now() - this.windowMs;
|
|
124
|
+
// Find first entry within window using binary-ish scan
|
|
125
|
+
let i = 0;
|
|
126
|
+
while (i < this.entries.length && this.entries[i].timestamp < cutoff) {
|
|
127
|
+
i++;
|
|
128
|
+
}
|
|
129
|
+
if (i > 0) {
|
|
130
|
+
this.entries = this.entries.slice(i);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Calculate percentile from sorted array
|
|
135
|
+
*/
|
|
136
|
+
percentile(sorted, p) {
|
|
137
|
+
if (sorted.length === 0)
|
|
138
|
+
return 0;
|
|
139
|
+
const index = Math.ceil((p / 100) * sorted.length) - 1;
|
|
140
|
+
return sorted[Math.max(0, index)];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.MetricsCollector = MetricsCollector;
|
|
144
|
+
/**
|
|
145
|
+
* Global registry of metrics collectors, keyed by name
|
|
146
|
+
*/
|
|
147
|
+
class MetricsRegistry {
|
|
148
|
+
static getOrCreate(name, windowMs) {
|
|
149
|
+
let collector = this.collectors.get(name);
|
|
150
|
+
if (!collector) {
|
|
151
|
+
collector = new MetricsCollector(windowMs);
|
|
152
|
+
this.collectors.set(name, collector);
|
|
153
|
+
}
|
|
154
|
+
return collector;
|
|
155
|
+
}
|
|
156
|
+
static get(name) {
|
|
157
|
+
return this.collectors.get(name);
|
|
158
|
+
}
|
|
159
|
+
static getAll() {
|
|
160
|
+
return new Map(this.collectors);
|
|
161
|
+
}
|
|
162
|
+
static remove(name) {
|
|
163
|
+
return this.collectors.delete(name);
|
|
164
|
+
}
|
|
165
|
+
static clear() {
|
|
166
|
+
this.collectors.clear();
|
|
167
|
+
}
|
|
168
|
+
static getSnapshot(name) {
|
|
169
|
+
return this.collectors.get(name)?.getSnapshot();
|
|
170
|
+
}
|
|
171
|
+
static getAllSnapshots() {
|
|
172
|
+
const snapshots = {};
|
|
173
|
+
for (const [name, collector] of this.collectors) {
|
|
174
|
+
snapshots[name] = collector.getSnapshot();
|
|
175
|
+
}
|
|
176
|
+
return snapshots;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.MetricsRegistry = MetricsRegistry;
|
|
180
|
+
MetricsRegistry.collectors = new Map();
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter
|
|
3
|
+
* Token bucket and sliding window implementations for rate limiting.
|
|
4
|
+
*/
|
|
5
|
+
import { RateLimiterConfig, RateLimiterStrategy } from '../types';
|
|
6
|
+
/**
|
|
7
|
+
* Token Bucket Rate Limiter
|
|
8
|
+
* Allows bursts up to the bucket capacity and refills at a steady rate.
|
|
9
|
+
*/
|
|
10
|
+
export declare class TokenBucketLimiter {
|
|
11
|
+
private tokens;
|
|
12
|
+
private lastRefill;
|
|
13
|
+
private capacity;
|
|
14
|
+
private refillRate;
|
|
15
|
+
constructor(capacity: number, refillRatePerSecond: number);
|
|
16
|
+
/**
|
|
17
|
+
* Try to consume a token. Returns true if allowed.
|
|
18
|
+
*/
|
|
19
|
+
tryAcquire(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Get time in ms until the next token is available
|
|
22
|
+
*/
|
|
23
|
+
getRetryAfterMs(): number;
|
|
24
|
+
private refill;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Sliding Window Counter Rate Limiter
|
|
28
|
+
* Tracks request counts in small sub-windows for more accurate rate limiting.
|
|
29
|
+
*/
|
|
30
|
+
export declare class SlidingWindowLimiter {
|
|
31
|
+
private windows;
|
|
32
|
+
private max;
|
|
33
|
+
private windowMs;
|
|
34
|
+
private subWindowMs;
|
|
35
|
+
constructor(max: number, windowMs: number);
|
|
36
|
+
/**
|
|
37
|
+
* Try to record a request. Returns true if within limit.
|
|
38
|
+
*/
|
|
39
|
+
tryAcquire(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Get time in ms until a slot opens up
|
|
42
|
+
*/
|
|
43
|
+
getRetryAfterMs(): number;
|
|
44
|
+
private getCurrentCount;
|
|
45
|
+
private getCurrentSubKey;
|
|
46
|
+
private evict;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Unified RateLimiter that wraps the configured strategy
|
|
50
|
+
*/
|
|
51
|
+
export declare class RateLimiter {
|
|
52
|
+
private limiter;
|
|
53
|
+
private strategy;
|
|
54
|
+
constructor(config: RateLimiterConfig);
|
|
55
|
+
/**
|
|
56
|
+
* Execute a function within rate limit constraints
|
|
57
|
+
*/
|
|
58
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
59
|
+
/**
|
|
60
|
+
* Try to acquire permission (consumes a token/slot)
|
|
61
|
+
*/
|
|
62
|
+
tryAcquire(): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Get time in ms until the next request is allowed
|
|
65
|
+
*/
|
|
66
|
+
getRetryAfterMs(): number;
|
|
67
|
+
/**
|
|
68
|
+
* Get the strategy in use
|
|
69
|
+
*/
|
|
70
|
+
getStrategy(): RateLimiterStrategy;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|