@defai.digital/provider-domain 13.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.
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Health Monitor Implementation
3
+ *
4
+ * Tracks provider health through latency, error rates, and availability.
5
+ * Enables intelligent routing based on provider health status.
6
+ *
7
+ * Invariants:
8
+ * - INV-HM-001: Latency samples bounded by configured size
9
+ * - INV-HM-002: Error rate calculated over sliding window
10
+ * - INV-HM-003: Availability derived from circuit and error state
11
+ */
12
+ import { createDefaultHealthCheckConfig, calculatePercentile, HealthErrorCodes, } from '@defai.digital/contracts';
13
+ /**
14
+ * Creates a health monitor for a provider
15
+ */
16
+ export function createHealthMonitor(providerId, config = {}, healthCheckFn) {
17
+ const cfg = { ...createDefaultHealthCheckConfig(), ...config };
18
+ // Latency tracking (INV-HM-001)
19
+ const latencySamples = [];
20
+ // Request tracking (INV-HM-002)
21
+ let totalRequests = 0;
22
+ let totalErrors = 0;
23
+ let consecutiveFailures = 0;
24
+ let consecutiveSuccesses = 0;
25
+ // Timestamps
26
+ let lastCheckTime = new Date();
27
+ let lastSuccessTime;
28
+ let lastErrorTime;
29
+ let lastError;
30
+ let lastErrorCode;
31
+ // External state
32
+ let circuitState = 'closed';
33
+ let rateLimitState = 'normal';
34
+ // Current health level
35
+ let currentLevel = 'unknown';
36
+ const events = [];
37
+ const listeners = [];
38
+ function emitEvent(type, details) {
39
+ const previousLevel = currentLevel;
40
+ updateHealthLevel();
41
+ const event = {
42
+ eventId: crypto.randomUUID(),
43
+ type,
44
+ providerId,
45
+ timestamp: new Date().toISOString(),
46
+ previousLevel,
47
+ currentLevel,
48
+ details,
49
+ };
50
+ events.push(event);
51
+ listeners.forEach((listener) => { listener(event); });
52
+ }
53
+ // INV-HM-001: Maintain bounded latency samples
54
+ function addLatencySample(latencyMs) {
55
+ latencySamples.push(latencyMs);
56
+ if (latencySamples.length > cfg.latencySampleSize) {
57
+ latencySamples.shift();
58
+ }
59
+ }
60
+ function calculateAverageLatency() {
61
+ if (latencySamples.length === 0)
62
+ return 0;
63
+ const sum = latencySamples.reduce((a, b) => a + b, 0);
64
+ return sum / latencySamples.length;
65
+ }
66
+ // INV-HM-002: Calculate error rate over window
67
+ function calculateErrorRate() {
68
+ if (totalRequests === 0)
69
+ return 0;
70
+ return totalErrors / totalRequests;
71
+ }
72
+ // INV-HM-003: Derive availability from state
73
+ function updateHealthLevel() {
74
+ const errorRate = calculateErrorRate();
75
+ const previousLevel = currentLevel;
76
+ // Circuit open = unhealthy
77
+ if (circuitState === 'open') {
78
+ currentLevel = 'unhealthy';
79
+ }
80
+ // High error rate = unhealthy
81
+ else if (errorRate >= cfg.unhealthyErrorRate) {
82
+ currentLevel = 'unhealthy';
83
+ }
84
+ // Degraded conditions
85
+ else if (circuitState === 'halfOpen' ||
86
+ rateLimitState === 'throttled' ||
87
+ rateLimitState === 'blocked' ||
88
+ consecutiveFailures >= cfg.degradedThreshold) {
89
+ currentLevel = 'degraded';
90
+ }
91
+ // No data yet
92
+ else if (totalRequests === 0) {
93
+ currentLevel = 'unknown';
94
+ }
95
+ // All good
96
+ else {
97
+ currentLevel = 'healthy';
98
+ }
99
+ // Emit level change events
100
+ if (previousLevel !== currentLevel) {
101
+ if (currentLevel === 'unhealthy') {
102
+ emitEvent('health.unhealthy');
103
+ }
104
+ else if (currentLevel === 'degraded') {
105
+ emitEvent('health.degraded');
106
+ }
107
+ else if (currentLevel === 'healthy' &&
108
+ (previousLevel === 'degraded' || previousLevel === 'unhealthy')) {
109
+ emitEvent('health.recovered');
110
+ }
111
+ }
112
+ }
113
+ function isAvailable() {
114
+ return currentLevel === 'healthy' || currentLevel === 'degraded';
115
+ }
116
+ return {
117
+ getStatus() {
118
+ updateHealthLevel();
119
+ const sortedLatencies = [...latencySamples].sort((a, b) => a - b);
120
+ return {
121
+ providerId,
122
+ available: isAvailable(),
123
+ level: currentLevel,
124
+ latencyMs: calculateAverageLatency(),
125
+ latencyP50Ms: sortedLatencies.length > 0
126
+ ? calculatePercentile(sortedLatencies, 50)
127
+ : undefined,
128
+ latencyP95Ms: sortedLatencies.length > 0
129
+ ? calculatePercentile(sortedLatencies, 95)
130
+ : undefined,
131
+ latencyP99Ms: sortedLatencies.length > 0
132
+ ? calculatePercentile(sortedLatencies, 99)
133
+ : undefined,
134
+ errorRate: calculateErrorRate(),
135
+ consecutiveFailures,
136
+ consecutiveSuccesses,
137
+ lastCheckTime: lastCheckTime.toISOString(),
138
+ lastSuccessTime: lastSuccessTime?.toISOString(),
139
+ lastErrorTime: lastErrorTime?.toISOString(),
140
+ lastError,
141
+ lastErrorCode,
142
+ circuitState,
143
+ rateLimitState,
144
+ totalRequests,
145
+ totalErrors,
146
+ uptimePercent: totalRequests > 0
147
+ ? ((totalRequests - totalErrors) / totalRequests) * 100
148
+ : undefined,
149
+ };
150
+ },
151
+ recordSuccess(latencyMs) {
152
+ totalRequests++;
153
+ consecutiveSuccesses++;
154
+ consecutiveFailures = 0;
155
+ lastSuccessTime = new Date();
156
+ lastCheckTime = new Date();
157
+ addLatencySample(latencyMs);
158
+ emitEvent('health.check.passed', { latencyMs });
159
+ },
160
+ recordFailure(error, errorCode) {
161
+ totalRequests++;
162
+ totalErrors++;
163
+ consecutiveFailures++;
164
+ consecutiveSuccesses = 0;
165
+ lastErrorTime = new Date();
166
+ lastCheckTime = new Date();
167
+ lastError = error;
168
+ lastErrorCode = errorCode;
169
+ emitEvent('health.check.failed', { error, errorCode });
170
+ },
171
+ updateCircuitState(state) {
172
+ const previous = circuitState;
173
+ circuitState = state;
174
+ if (previous !== state) {
175
+ updateHealthLevel();
176
+ emitEvent('health.status.changed', {
177
+ circuitState: state,
178
+ previousCircuitState: previous,
179
+ });
180
+ }
181
+ },
182
+ updateRateLimitState(state) {
183
+ const previous = rateLimitState;
184
+ rateLimitState = state;
185
+ if (previous !== state) {
186
+ updateHealthLevel();
187
+ emitEvent('health.status.changed', {
188
+ rateLimitState: state,
189
+ previousRateLimitState: previous,
190
+ });
191
+ }
192
+ },
193
+ async performHealthCheck() {
194
+ const checkId = crypto.randomUUID();
195
+ const startTime = Date.now();
196
+ emitEvent('health.check.started', { checkId });
197
+ if (!healthCheckFn) {
198
+ // No health check function provided, return unknown
199
+ return {
200
+ checkId,
201
+ providerId,
202
+ success: false,
203
+ latencyMs: 0,
204
+ timestamp: new Date().toISOString(),
205
+ error: 'No health check function configured',
206
+ errorCode: HealthErrorCodes.CHECK_FAILED,
207
+ checkType: 'active',
208
+ };
209
+ }
210
+ // Create cancellable timeout to prevent timer leaks
211
+ let timeoutId;
212
+ const timeoutPromise = new Promise((_, reject) => {
213
+ timeoutId = setTimeout(() => { reject(new Error('Health check timeout')); }, cfg.timeoutMs);
214
+ });
215
+ try {
216
+ const result = await Promise.race([
217
+ healthCheckFn(),
218
+ timeoutPromise,
219
+ ]);
220
+ // Clean up timeout
221
+ if (timeoutId !== undefined) {
222
+ clearTimeout(timeoutId);
223
+ }
224
+ const latencyMs = Date.now() - startTime;
225
+ if (result.success) {
226
+ this.recordSuccess(latencyMs);
227
+ }
228
+ else {
229
+ this.recordFailure(result.error ?? 'Health check failed', HealthErrorCodes.CHECK_FAILED);
230
+ }
231
+ return {
232
+ checkId,
233
+ providerId,
234
+ success: result.success,
235
+ latencyMs,
236
+ timestamp: new Date().toISOString(),
237
+ error: result.error,
238
+ checkType: 'active',
239
+ };
240
+ }
241
+ catch (error) {
242
+ // Clean up timeout on error too
243
+ if (timeoutId !== undefined) {
244
+ clearTimeout(timeoutId);
245
+ }
246
+ const latencyMs = Date.now() - startTime;
247
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
248
+ this.recordFailure(errorMessage, HealthErrorCodes.CHECK_TIMEOUT);
249
+ return {
250
+ checkId,
251
+ providerId,
252
+ success: false,
253
+ latencyMs,
254
+ timestamp: new Date().toISOString(),
255
+ error: errorMessage,
256
+ errorCode: HealthErrorCodes.CHECK_TIMEOUT,
257
+ checkType: 'active',
258
+ };
259
+ }
260
+ },
261
+ getEvents() {
262
+ return [...events];
263
+ },
264
+ reset() {
265
+ latencySamples.length = 0;
266
+ totalRequests = 0;
267
+ totalErrors = 0;
268
+ consecutiveFailures = 0;
269
+ consecutiveSuccesses = 0;
270
+ lastCheckTime = new Date();
271
+ lastSuccessTime = undefined;
272
+ lastErrorTime = undefined;
273
+ lastError = undefined;
274
+ lastErrorCode = undefined;
275
+ circuitState = 'closed';
276
+ rateLimitState = 'normal';
277
+ currentLevel = 'unknown';
278
+ events.length = 0;
279
+ },
280
+ };
281
+ }
282
+ /**
283
+ * Health monitor error
284
+ */
285
+ export class HealthMonitorError extends Error {
286
+ code;
287
+ providerId;
288
+ constructor(code, providerId, message) {
289
+ super(message);
290
+ this.code = code;
291
+ this.providerId = providerId;
292
+ this.name = 'HealthMonitorError';
293
+ }
294
+ static checkTimeout(providerId) {
295
+ return new HealthMonitorError(HealthErrorCodes.CHECK_TIMEOUT, providerId, `Health check timed out for provider ${providerId}`);
296
+ }
297
+ static providerUnavailable(providerId) {
298
+ return new HealthMonitorError(HealthErrorCodes.PROVIDER_UNAVAILABLE, providerId, `Provider ${providerId} is unavailable`);
299
+ }
300
+ }
301
+ //# sourceMappingURL=health-monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-monitor.js","sourceRoot":"","sources":["../src/health-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EASL,8BAA8B,EAC9B,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AA6ClC;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,SAAqC,EAAE,EACvC,aAA6B;IAE7B,MAAM,GAAG,GAAG,EAAE,GAAG,8BAA8B,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC;IAE/D,gCAAgC;IAChC,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,gCAAgC;IAChC,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAC5B,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAE7B,aAAa;IACb,IAAI,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC;IAC/B,IAAI,eAAiC,CAAC;IACtC,IAAI,aAA+B,CAAC;IACpC,IAAI,SAA6B,CAAC;IAClC,IAAI,aAAiC,CAAC;IAEtC,iBAAiB;IACjB,IAAI,YAAY,GAAiB,QAAQ,CAAC;IAC1C,IAAI,cAAc,GAAuB,QAAQ,CAAC;IAElD,uBAAuB;IACvB,IAAI,YAAY,GAAgB,SAAS,CAAC;IAE1C,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,SAAS,GAA0B,EAAE,CAAC;IAE5C,SAAS,SAAS,CAChB,IAAqB,EACrB,OAAiC;QAEjC,MAAM,aAAa,GAAG,YAAY,CAAC;QACnC,iBAAiB,EAAE,CAAC;QAEpB,MAAM,KAAK,GAAgB;YACzB,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE;YAC5B,IAAI;YACJ,UAAU;YACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,aAAa;YACb,YAAY;YACZ,OAAO;SACR,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,+CAA+C;IAC/C,SAAS,gBAAgB,CAAC,SAAiB;QACzC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,IAAI,cAAc,CAAC,MAAM,GAAG,GAAG,CAAC,iBAAiB,EAAE,CAAC;YAClD,cAAc,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED,SAAS,uBAAuB;QAC9B,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACtD,OAAO,GAAG,GAAG,cAAc,CAAC,MAAM,CAAC;IACrC,CAAC;IAED,+CAA+C;IAC/C,SAAS,kBAAkB;QACzB,IAAI,aAAa,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAClC,OAAO,WAAW,GAAG,aAAa,CAAC;IACrC,CAAC;IAED,6CAA6C;IAC7C,SAAS,iBAAiB;QACxB,MAAM,SAAS,GAAG,kBAAkB,EAAE,CAAC;QACvC,MAAM,aAAa,GAAG,YAAY,CAAC;QAEnC,2BAA2B;QAC3B,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YAC5B,YAAY,GAAG,WAAW,CAAC;QAC7B,CAAC;QACD,8BAA8B;aACzB,IAAI,SAAS,IAAI,GAAG,CAAC,kBAAkB,EAAE,CAAC;YAC7C,YAAY,GAAG,WAAW,CAAC;QAC7B,CAAC;QACD,sBAAsB;aACjB,IACH,YAAY,KAAK,UAAU;YAC3B,cAAc,KAAK,WAAW;YAC9B,cAAc,KAAK,SAAS;YAC5B,mBAAmB,IAAI,GAAG,CAAC,iBAAiB,EAC5C,CAAC;YACD,YAAY,GAAG,UAAU,CAAC;QAC5B,CAAC;QACD,cAAc;aACT,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;YAC7B,YAAY,GAAG,SAAS,CAAC;QAC3B,CAAC;QACD,WAAW;aACN,CAAC;YACJ,YAAY,GAAG,SAAS,CAAC;QAC3B,CAAC;QAED,2BAA2B;QAC3B,IAAI,aAAa,KAAK,YAAY,EAAE,CAAC;YACnC,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;gBACjC,SAAS,CAAC,kBAAkB,CAAC,CAAC;YAChC,CAAC;iBAAM,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;gBACvC,SAAS,CAAC,iBAAiB,CAAC,CAAC;YAC/B,CAAC;iBAAM,IACL,YAAY,KAAK,SAAS;gBAC1B,CAAC,aAAa,KAAK,UAAU,IAAI,aAAa,KAAK,WAAW,CAAC,EAC/D,CAAC;gBACD,SAAS,CAAC,kBAAkB,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,WAAW;QAClB,OAAO,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,UAAU,CAAC;IACnE,CAAC;IAED,OAAO;QACL,SAAS;YACP,iBAAiB,EAAE,CAAC;YACpB,MAAM,eAAe,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAElE,OAAO;gBACL,UAAU;gBACV,SAAS,EAAE,WAAW,EAAE;gBACxB,KAAK,EAAE,YAAY;gBACnB,SAAS,EAAE,uBAAuB,EAAE;gBACpC,YAAY,EACV,eAAe,CAAC,MAAM,GAAG,CAAC;oBACxB,CAAC,CAAC,mBAAmB,CAAC,eAAe,EAAE,EAAE,CAAC;oBAC1C,CAAC,CAAC,SAAS;gBACf,YAAY,EACV,eAAe,CAAC,MAAM,GAAG,CAAC;oBACxB,CAAC,CAAC,mBAAmB,CAAC,eAAe,EAAE,EAAE,CAAC;oBAC1C,CAAC,CAAC,SAAS;gBACf,YAAY,EACV,eAAe,CAAC,MAAM,GAAG,CAAC;oBACxB,CAAC,CAAC,mBAAmB,CAAC,eAAe,EAAE,EAAE,CAAC;oBAC1C,CAAC,CAAC,SAAS;gBACf,SAAS,EAAE,kBAAkB,EAAE;gBAC/B,mBAAmB;gBACnB,oBAAoB;gBACpB,aAAa,EAAE,aAAa,CAAC,WAAW,EAAE;gBAC1C,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE;gBAC/C,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE;gBAC3C,SAAS;gBACT,aAAa;gBACb,YAAY;gBACZ,cAAc;gBACd,aAAa;gBACb,WAAW;gBACX,aAAa,EACX,aAAa,GAAG,CAAC;oBACf,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,WAAW,CAAC,GAAG,aAAa,CAAC,GAAG,GAAG;oBACvD,CAAC,CAAC,SAAS;aAChB,CAAC;QACJ,CAAC;QAED,aAAa,CAAC,SAAiB;YAC7B,aAAa,EAAE,CAAC;YAChB,oBAAoB,EAAE,CAAC;YACvB,mBAAmB,GAAG,CAAC,CAAC;YACxB,eAAe,GAAG,IAAI,IAAI,EAAE,CAAC;YAC7B,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC;YAE3B,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC5B,SAAS,CAAC,qBAAqB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAClD,CAAC;QAED,aAAa,CAAC,KAAa,EAAE,SAAkB;YAC7C,aAAa,EAAE,CAAC;YAChB,WAAW,EAAE,CAAC;YACd,mBAAmB,EAAE,CAAC;YACtB,oBAAoB,GAAG,CAAC,CAAC;YACzB,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC;YAC3B,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC;YAC3B,SAAS,GAAG,KAAK,CAAC;YAClB,aAAa,GAAG,SAAS,CAAC;YAE1B,SAAS,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,kBAAkB,CAAC,KAAmB;YACpC,MAAM,QAAQ,GAAG,YAAY,CAAC;YAC9B,YAAY,GAAG,KAAK,CAAC;YACrB,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;gBACvB,iBAAiB,EAAE,CAAC;gBACpB,SAAS,CAAC,uBAAuB,EAAE;oBACjC,YAAY,EAAE,KAAK;oBACnB,oBAAoB,EAAE,QAAQ;iBAC/B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,oBAAoB,CAAC,KAAyB;YAC5C,MAAM,QAAQ,GAAG,cAAc,CAAC;YAChC,cAAc,GAAG,KAAK,CAAC;YACvB,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;gBACvB,iBAAiB,EAAE,CAAC;gBACpB,SAAS,CAAC,uBAAuB,EAAE;oBACjC,cAAc,EAAE,KAAK;oBACrB,sBAAsB,EAAE,QAAQ;iBACjC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,KAAK,CAAC,kBAAkB;YACtB,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAE7B,SAAS,CAAC,sBAAsB,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;YAE/C,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,oDAAoD;gBACpD,OAAO;oBACL,OAAO;oBACP,UAAU;oBACV,OAAO,EAAE,KAAK;oBACd,SAAS,EAAE,CAAC;oBACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBACnC,KAAK,EAAE,qCAAqC;oBAC5C,SAAS,EAAE,gBAAgB,CAAC,YAAY;oBACxC,SAAS,EAAE,QAAQ;iBACpB,CAAC;YACJ,CAAC;YAED,oDAAoD;YACpD,IAAI,SAAoD,CAAC;YACzD,MAAM,cAAc,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;gBACtD,SAAS,GAAG,UAAU,CACpB,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,EACpD,GAAG,CAAC,SAAS,CACd,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;oBAChC,aAAa,EAAE;oBACf,cAAc;iBACf,CAAC,CAAC;gBAEH,mBAAmB;gBACnB,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;oBAC5B,YAAY,CAAC,SAAS,CAAC,CAAC;gBAC1B,CAAC;gBAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;gBAEzC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACnB,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;gBAChC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,aAAa,CAChB,MAAM,CAAC,KAAK,IAAI,qBAAqB,EACrC,gBAAgB,CAAC,YAAY,CAC9B,CAAC;gBACJ,CAAC;gBAED,OAAO;oBACL,OAAO;oBACP,UAAU;oBACV,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,SAAS;oBACT,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBACnC,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,SAAS,EAAE,QAAQ;iBACpB,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,gCAAgC;gBAChC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;oBAC5B,YAAY,CAAC,SAAS,CAAC,CAAC;gBAC1B,CAAC;gBACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;gBACzC,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;gBAE3D,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAC;gBAEjE,OAAO;oBACL,OAAO;oBACP,UAAU;oBACV,OAAO,EAAE,KAAK;oBACd,SAAS;oBACT,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBACnC,KAAK,EAAE,YAAY;oBACnB,SAAS,EAAE,gBAAgB,CAAC,aAAa;oBACzC,SAAS,EAAE,QAAQ;iBACpB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,SAAS;YACP,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;QACrB,CAAC;QAED,KAAK;YACH,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;YAC1B,aAAa,GAAG,CAAC,CAAC;YAClB,WAAW,GAAG,CAAC,CAAC;YAChB,mBAAmB,GAAG,CAAC,CAAC;YACxB,oBAAoB,GAAG,CAAC,CAAC;YACzB,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC;YAC3B,eAAe,GAAG,SAAS,CAAC;YAC5B,aAAa,GAAG,SAAS,CAAC;YAC1B,SAAS,GAAG,SAAS,CAAC;YACtB,aAAa,GAAG,SAAS,CAAC;YAC1B,YAAY,GAAG,QAAQ,CAAC;YACxB,cAAc,GAAG,QAAQ,CAAC;YAC1B,YAAY,GAAG,SAAS,CAAC;YACzB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAEzB;IACA;IAFlB,YACkB,IAAY,EACZ,UAAkB,EAClC,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,SAAI,GAAJ,IAAI,CAAQ;QACZ,eAAU,GAAV,UAAU,CAAQ;QAIlC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,UAAkB;QACpC,OAAO,IAAI,kBAAkB,CAC3B,gBAAgB,CAAC,aAAa,EAC9B,UAAU,EACV,uCAAuC,UAAU,EAAE,CACpD,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,mBAAmB,CAAC,UAAkB;QAC3C,OAAO,IAAI,kBAAkB,CAC3B,gBAAgB,CAAC,oBAAoB,EACrC,UAAU,EACV,YAAY,UAAU,iBAAiB,CACxC,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @defai.digital/provider-domain
3
+ *
4
+ * Provider Resilience Domain
5
+ *
6
+ * Provides circuit breaker, rate limiting, and health monitoring
7
+ * for intelligent provider management and fault tolerance.
8
+ */
9
+ export { createCircuitBreaker, CircuitBreakerError, type CircuitBreaker, type CircuitEventListener, } from './circuit-breaker.js';
10
+ export { createRateLimiter, RateLimitError, type RateLimiter, type RateLimitEventListener, } from './rate-limiter.js';
11
+ export { createHealthMonitor, HealthMonitorError, type HealthMonitor, type HealthEventListener, type HealthCheckFn, } from './health-monitor.js';
12
+ export { createManagedProvider, createProviderManager, type ProviderConfig, type ManagedProvider, type ProviderManager, } from './provider-manager.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @defai.digital/provider-domain
3
+ *
4
+ * Provider Resilience Domain
5
+ *
6
+ * Provides circuit breaker, rate limiting, and health monitoring
7
+ * for intelligent provider management and fault tolerance.
8
+ */
9
+ // Circuit Breaker
10
+ export { createCircuitBreaker, CircuitBreakerError, } from './circuit-breaker.js';
11
+ // Rate Limiter
12
+ export { createRateLimiter, RateLimitError, } from './rate-limiter.js';
13
+ // Health Monitor
14
+ export { createHealthMonitor, HealthMonitorError, } from './health-monitor.js';
15
+ // Provider Manager
16
+ export { createManagedProvider, createProviderManager, } from './provider-manager.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,kBAAkB;AAClB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,GAGpB,MAAM,sBAAsB,CAAC;AAE9B,eAAe;AACf,OAAO,EACL,iBAAiB,EACjB,cAAc,GAGf,MAAM,mBAAmB,CAAC;AAE3B,iBAAiB;AACjB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,GAInB,MAAM,qBAAqB,CAAC;AAE7B,mBAAmB;AACnB,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GAItB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Provider Manager
3
+ *
4
+ * Integrates circuit breaker, rate limiter, and health monitor
5
+ * to provide unified provider resilience management.
6
+ *
7
+ * This is the main entry point for provider resilience features.
8
+ */
9
+ import type { ProviderCircuitBreakerConfig as CircuitBreakerConfig, ProviderRateLimitConfig as RateLimitConfig, HealthCheckConfig, HealthStatus } from '@defai.digital/contracts';
10
+ import { CircuitBreaker } from './circuit-breaker.js';
11
+ import { RateLimiter } from './rate-limiter.js';
12
+ import { HealthMonitor, HealthCheckFn } from './health-monitor.js';
13
+ /**
14
+ * Provider configuration
15
+ */
16
+ export interface ProviderConfig {
17
+ /** Provider identifier */
18
+ providerId: string;
19
+ /** Circuit breaker configuration */
20
+ circuitBreaker?: Partial<CircuitBreakerConfig>;
21
+ /** Rate limiter configuration */
22
+ rateLimiter?: Partial<RateLimitConfig>;
23
+ /** Health monitor configuration */
24
+ healthMonitor?: Partial<HealthCheckConfig>;
25
+ /** Health check function for active checks */
26
+ healthCheckFn?: HealthCheckFn;
27
+ }
28
+ /**
29
+ * Managed provider with resilience features
30
+ */
31
+ export interface ManagedProvider {
32
+ /** Provider identifier */
33
+ readonly providerId: string;
34
+ /** Circuit breaker instance */
35
+ readonly circuitBreaker: CircuitBreaker;
36
+ /** Rate limiter instance */
37
+ readonly rateLimiter: RateLimiter;
38
+ /** Health monitor instance */
39
+ readonly healthMonitor: HealthMonitor;
40
+ /** Check if provider can handle a request */
41
+ canExecute(tokens?: number): boolean;
42
+ /** Execute a request with resilience wrapping */
43
+ execute<T>(fn: () => Promise<T>, tokens?: number): Promise<T>;
44
+ /** Get combined health status */
45
+ getHealth(): HealthStatus;
46
+ /** Reset all resilience state */
47
+ reset(): void;
48
+ }
49
+ /**
50
+ * Provider manager for multiple providers
51
+ */
52
+ export interface ProviderManager {
53
+ /** Register a provider */
54
+ register(config: ProviderConfig): ManagedProvider;
55
+ /** Get a registered provider */
56
+ get(providerId: string): ManagedProvider | undefined;
57
+ /** List all registered providers */
58
+ list(): ManagedProvider[];
59
+ /** Get health status for all providers */
60
+ getHealthAll(): Map<string, HealthStatus>;
61
+ /** Get the healthiest available provider */
62
+ selectBest(providerIds?: string[]): ManagedProvider | undefined;
63
+ /** Remove a provider */
64
+ remove(providerId: string): boolean;
65
+ /** Reset all providers */
66
+ resetAll(): void;
67
+ }
68
+ /**
69
+ * Creates a managed provider with integrated resilience
70
+ */
71
+ export declare function createManagedProvider(config: ProviderConfig): ManagedProvider;
72
+ /**
73
+ * Creates a provider manager
74
+ */
75
+ export declare function createProviderManager(): ProviderManager;
76
+ //# sourceMappingURL=provider-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-manager.d.ts","sourceRoot":"","sources":["../src/provider-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,4BAA4B,IAAI,oBAAoB,EACpD,uBAAuB,IAAI,eAAe,EAC1C,iBAAiB,EACjB,YAAY,EACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAEL,cAAc,EAEf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,WAAW,EAEZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,aAAa,EACb,aAAa,EACd,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IAEnB,oCAAoC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAE/C,iCAAiC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAEvC,mCAAmC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAE3C,8CAA8C;IAC9C,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,+BAA+B;IAC/B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAExC,4BAA4B;IAC5B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAElC,8BAA8B;IAC9B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IAEtC,6CAA6C;IAC7C,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAErC,iDAAiD;IACjD,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE9D,iCAAiC;IACjC,SAAS,IAAI,YAAY,CAAC;IAE1B,iCAAiC;IACjC,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,CAAC;IAElD,gCAAgC;IAChC,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IAErD,oCAAoC;IACpC,IAAI,IAAI,eAAe,EAAE,CAAC;IAE1B,0CAA0C;IAC1C,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAE1C,4CAA4C;IAC5C,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,eAAe,GAAG,SAAS,CAAC;IAEhE,wBAAwB;IACxB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAEpC,0BAA0B;IAC1B,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,CAkG7E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CA6EvD"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Provider Manager
3
+ *
4
+ * Integrates circuit breaker, rate limiter, and health monitor
5
+ * to provide unified provider resilience management.
6
+ *
7
+ * This is the main entry point for provider resilience features.
8
+ */
9
+ import { createCircuitBreaker, CircuitBreakerError, } from './circuit-breaker.js';
10
+ import { createRateLimiter, RateLimitError, } from './rate-limiter.js';
11
+ import { createHealthMonitor, } from './health-monitor.js';
12
+ /**
13
+ * Creates a managed provider with integrated resilience
14
+ */
15
+ export function createManagedProvider(config) {
16
+ const { providerId, circuitBreaker: cbConfig, rateLimiter: rlConfig, healthMonitor: hmConfig, healthCheckFn, } = config;
17
+ const circuitBreaker = createCircuitBreaker(providerId, cbConfig);
18
+ const rateLimiter = createRateLimiter(providerId, rlConfig);
19
+ const healthMonitor = createHealthMonitor(providerId, hmConfig, healthCheckFn);
20
+ // Sync circuit breaker state to health monitor
21
+ const originalRecordSuccess = circuitBreaker.recordSuccess.bind(circuitBreaker);
22
+ const originalRecordFailure = circuitBreaker.recordFailure.bind(circuitBreaker);
23
+ circuitBreaker.recordSuccess = () => {
24
+ originalRecordSuccess();
25
+ healthMonitor.updateCircuitState(circuitBreaker.getState().state);
26
+ };
27
+ circuitBreaker.recordFailure = (error) => {
28
+ originalRecordFailure(error);
29
+ healthMonitor.updateCircuitState(circuitBreaker.getState().state);
30
+ };
31
+ // Sync rate limiter state to health monitor
32
+ const originalTryConsume = rateLimiter.tryConsume.bind(rateLimiter);
33
+ rateLimiter.tryConsume = (tokens) => {
34
+ const result = originalTryConsume(tokens);
35
+ healthMonitor.updateRateLimitState(rateLimiter.getState().state);
36
+ return result;
37
+ };
38
+ return {
39
+ providerId,
40
+ circuitBreaker,
41
+ rateLimiter,
42
+ healthMonitor,
43
+ canExecute(tokens = 1) {
44
+ return circuitBreaker.canExecute() && rateLimiter.canRequest(tokens);
45
+ },
46
+ async execute(fn, tokens = 1) {
47
+ // Check circuit breaker
48
+ if (!circuitBreaker.canExecute()) {
49
+ throw CircuitBreakerError.circuitOpen(providerId);
50
+ }
51
+ // Check rate limiter
52
+ if (!rateLimiter.tryConsume(tokens)) {
53
+ const waitTime = rateLimiter.getWaitTime(tokens);
54
+ throw RateLimitError.exceeded(providerId, waitTime);
55
+ }
56
+ const startTime = Date.now();
57
+ try {
58
+ const result = await fn();
59
+ const latencyMs = Date.now() - startTime;
60
+ // Record success
61
+ circuitBreaker.recordSuccess();
62
+ healthMonitor.recordSuccess(latencyMs);
63
+ return result;
64
+ }
65
+ catch (error) {
66
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
67
+ // Check if it's a rate limit error from the API
68
+ if (isRateLimitError(error)) {
69
+ const retryAfter = extractRetryAfter(error);
70
+ rateLimiter.recordExternalLimit(retryAfter);
71
+ healthMonitor.recordFailure(errorMessage, 'RATE_LIMIT');
72
+ throw RateLimitError.exceeded(providerId, retryAfter);
73
+ }
74
+ // Record failure
75
+ circuitBreaker.recordFailure(errorMessage);
76
+ healthMonitor.recordFailure(errorMessage);
77
+ throw error;
78
+ }
79
+ },
80
+ getHealth() {
81
+ return healthMonitor.getStatus();
82
+ },
83
+ reset() {
84
+ circuitBreaker.reset();
85
+ rateLimiter.reset();
86
+ healthMonitor.reset();
87
+ },
88
+ };
89
+ }
90
+ /**
91
+ * Creates a provider manager
92
+ */
93
+ export function createProviderManager() {
94
+ const providers = new Map();
95
+ return {
96
+ register(config) {
97
+ const provider = createManagedProvider(config);
98
+ providers.set(config.providerId, provider);
99
+ return provider;
100
+ },
101
+ get(providerId) {
102
+ return providers.get(providerId);
103
+ },
104
+ list() {
105
+ return Array.from(providers.values());
106
+ },
107
+ getHealthAll() {
108
+ const healthMap = new Map();
109
+ providers.forEach((provider, id) => {
110
+ healthMap.set(id, provider.getHealth());
111
+ });
112
+ return healthMap;
113
+ },
114
+ selectBest(providerIds) {
115
+ const candidates = providerIds
116
+ ? providerIds
117
+ .map((id) => providers.get(id))
118
+ .filter((p) => p !== undefined)
119
+ : Array.from(providers.values());
120
+ // Filter to available providers
121
+ const available = candidates.filter((p) => {
122
+ const health = p.getHealth();
123
+ return health.available && p.canExecute();
124
+ });
125
+ if (available.length === 0)
126
+ return undefined;
127
+ // Sort by health score (lower latency, lower error rate = better)
128
+ available.sort((a, b) => {
129
+ const healthA = a.getHealth();
130
+ const healthB = b.getHealth();
131
+ // Prefer healthy over degraded
132
+ if (healthA.level === 'healthy' && healthB.level !== 'healthy')
133
+ return -1;
134
+ if (healthB.level === 'healthy' && healthA.level !== 'healthy')
135
+ return 1;
136
+ // Then by error rate
137
+ const errorDiff = healthA.errorRate - healthB.errorRate;
138
+ if (Math.abs(errorDiff) > 0.1)
139
+ return errorDiff;
140
+ // Then by latency
141
+ return healthA.latencyMs - healthB.latencyMs;
142
+ });
143
+ return available[0];
144
+ },
145
+ remove(providerId) {
146
+ const provider = providers.get(providerId);
147
+ if (provider) {
148
+ provider.reset();
149
+ providers.delete(providerId);
150
+ return true;
151
+ }
152
+ return false;
153
+ },
154
+ resetAll() {
155
+ providers.forEach((provider) => {
156
+ provider.reset();
157
+ });
158
+ },
159
+ };
160
+ }
161
+ /**
162
+ * Helper to detect rate limit errors
163
+ */
164
+ function isRateLimitError(error) {
165
+ if (error instanceof Error) {
166
+ const message = error.message.toLowerCase();
167
+ return (message.includes('rate limit') ||
168
+ message.includes('too many requests') ||
169
+ message.includes('429'));
170
+ }
171
+ return false;
172
+ }
173
+ /**
174
+ * Helper to extract retry-after from error
175
+ */
176
+ function extractRetryAfter(error) {
177
+ if (error instanceof Error) {
178
+ // Try to extract from error message or properties
179
+ const match = /retry[- ]?after[:\s]*(\d+)/i.exec(error.message);
180
+ if (match?.[1]) {
181
+ return parseInt(match[1], 10) * 1000; // Convert to ms
182
+ }
183
+ }
184
+ return undefined;
185
+ }
186
+ //# sourceMappingURL=provider-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-manager.js","sourceRoot":"","sources":["../src/provider-manager.ts"],"names":[],"mappings":"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"}