@brutalist/mcp 0.6.0 → 0.6.1
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/README.md +3 -1
- package/dist/brutalist-server.d.ts +5 -0
- package/dist/brutalist-server.d.ts.map +1 -1
- package/dist/brutalist-server.js +244 -80
- package/dist/brutalist-server.js.map +1 -1
- package/dist/cli-agents.d.ts +7 -3
- package/dist/cli-agents.d.ts.map +1 -1
- package/dist/cli-agents.js +307 -48
- package/dist/cli-agents.js.map +1 -1
- package/dist/streaming/circuit-breaker.d.ts +186 -0
- package/dist/streaming/circuit-breaker.d.ts.map +1 -0
- package/dist/streaming/circuit-breaker.js +463 -0
- package/dist/streaming/circuit-breaker.js.map +1 -0
- package/dist/streaming/intelligent-buffer.d.ts +141 -0
- package/dist/streaming/intelligent-buffer.d.ts.map +1 -0
- package/dist/streaming/intelligent-buffer.js +555 -0
- package/dist/streaming/intelligent-buffer.js.map +1 -0
- package/dist/streaming/output-parser.d.ts +89 -0
- package/dist/streaming/output-parser.d.ts.map +1 -0
- package/dist/streaming/output-parser.js +349 -0
- package/dist/streaming/output-parser.js.map +1 -0
- package/dist/streaming/progress-tracker.d.ts +149 -0
- package/dist/streaming/progress-tracker.d.ts.map +1 -0
- package/dist/streaming/progress-tracker.js +519 -0
- package/dist/streaming/progress-tracker.js.map +1 -0
- package/dist/streaming/session-manager.d.ts +238 -0
- package/dist/streaming/session-manager.d.ts.map +1 -0
- package/dist/streaming/session-manager.js +546 -0
- package/dist/streaming/session-manager.js.map +1 -0
- package/dist/streaming/sse-transport.d.ts +95 -0
- package/dist/streaming/sse-transport.d.ts.map +1 -0
- package/dist/streaming/sse-transport.js +319 -0
- package/dist/streaming/sse-transport.js.map +1 -0
- package/dist/streaming/streaming-orchestrator.d.ts +153 -0
- package/dist/streaming/streaming-orchestrator.d.ts.map +1 -0
- package/dist/streaming/streaming-orchestrator.js +436 -0
- package/dist/streaming/streaming-orchestrator.js.map +1 -0
- package/dist/test-utils/process-manager.d.ts +61 -0
- package/dist/test-utils/process-manager.d.ts.map +1 -0
- package/dist/test-utils/process-manager.js +262 -0
- package/dist/test-utils/process-manager.js.map +1 -0
- package/dist/test-utils/server-harness.d.ts +73 -0
- package/dist/test-utils/server-harness.d.ts.map +1 -0
- package/dist/test-utils/server-harness.js +296 -0
- package/dist/test-utils/server-harness.js.map +1 -0
- package/dist/test-utils/streaming-fuzz.d.ts +57 -0
- package/dist/test-utils/streaming-fuzz.d.ts.map +1 -0
- package/dist/test-utils/streaming-fuzz.js +287 -0
- package/dist/test-utils/streaming-fuzz.js.map +1 -0
- package/dist/test-utils/test-isolation.d.ts +70 -0
- package/dist/test-utils/test-isolation.d.ts.map +1 -0
- package/dist/test-utils/test-isolation.js +193 -0
- package/dist/test-utils/test-isolation.js.map +1 -0
- package/dist/tool-definitions.d.ts.map +1 -1
- package/dist/tool-definitions.js +12 -6
- package/dist/tool-definitions.js.map +1 -1
- package/dist/types/brutalist.d.ts +3 -3
- package/dist/types/brutalist.d.ts.map +1 -1
- package/dist/types/tool-config.d.ts +0 -1
- package/dist/types/tool-config.d.ts.map +1 -1
- package/dist/types/tool-config.js +0 -1
- package/dist/types/tool-config.js.map +1 -1
- package/dist/utils/response-cache.d.ts +14 -7
- package/dist/utils/response-cache.d.ts.map +1 -1
- package/dist/utils/response-cache.js +173 -62
- package/dist/utils/response-cache.js.map +1 -1
- package/package.json +13 -3
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
/**
|
|
3
|
+
* Circuit breaker states
|
|
4
|
+
*/
|
|
5
|
+
export declare enum CircuitState {
|
|
6
|
+
CLOSED = "closed",// Normal operation
|
|
7
|
+
OPEN = "open",// Blocking requests due to failures
|
|
8
|
+
HALF_OPEN = "half_open"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Circuit breaker configuration
|
|
12
|
+
*/
|
|
13
|
+
export interface CircuitBreakerConfig {
|
|
14
|
+
failureThreshold: number;
|
|
15
|
+
recoveryTimeout: number;
|
|
16
|
+
successThreshold: number;
|
|
17
|
+
timeout: number;
|
|
18
|
+
monitoringWindow: number;
|
|
19
|
+
minimumRequests: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Circuit breaker statistics
|
|
23
|
+
*/
|
|
24
|
+
export interface CircuitStats {
|
|
25
|
+
state: CircuitState;
|
|
26
|
+
failures: number;
|
|
27
|
+
successes: number;
|
|
28
|
+
totalRequests: number;
|
|
29
|
+
lastFailureTime?: number;
|
|
30
|
+
lastSuccessTime?: number;
|
|
31
|
+
uptime: number;
|
|
32
|
+
failureRate: number;
|
|
33
|
+
averageResponseTime: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Request context for circuit breaker
|
|
37
|
+
*/
|
|
38
|
+
export interface RequestContext {
|
|
39
|
+
id: string;
|
|
40
|
+
startTime: number;
|
|
41
|
+
timeout: NodeJS.Timeout;
|
|
42
|
+
resolve: (value: any) => void;
|
|
43
|
+
reject: (reason: any) => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fallback strategy interface
|
|
47
|
+
*/
|
|
48
|
+
export interface FallbackStrategy {
|
|
49
|
+
execute(context: RequestContext, error: Error): Promise<any>;
|
|
50
|
+
canHandle(error: Error): boolean;
|
|
51
|
+
priority: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Circuit breaker with intelligent fallback handling
|
|
55
|
+
*
|
|
56
|
+
* Features:
|
|
57
|
+
* - Automatic failure detection and recovery
|
|
58
|
+
* - Configurable thresholds and timeouts
|
|
59
|
+
* - Multiple fallback strategies with priority
|
|
60
|
+
* - Real-time statistics and monitoring
|
|
61
|
+
* - Graceful degradation patterns
|
|
62
|
+
* - Request queuing during recovery
|
|
63
|
+
*/
|
|
64
|
+
export declare class CircuitBreaker extends EventEmitter {
|
|
65
|
+
private config;
|
|
66
|
+
private name;
|
|
67
|
+
private state;
|
|
68
|
+
private failures;
|
|
69
|
+
private successes;
|
|
70
|
+
private totalRequests;
|
|
71
|
+
private lastFailureTime?;
|
|
72
|
+
private lastSuccessTime?;
|
|
73
|
+
private recoveryTimer?;
|
|
74
|
+
private pendingRequests;
|
|
75
|
+
private fallbackStrategies;
|
|
76
|
+
private responseTimesWindow;
|
|
77
|
+
private requestTimesWindow;
|
|
78
|
+
constructor(config: CircuitBreakerConfig, name?: string);
|
|
79
|
+
/**
|
|
80
|
+
* Execute function with circuit breaker protection
|
|
81
|
+
*/
|
|
82
|
+
execute<T>(fn: () => Promise<T>, context?: {
|
|
83
|
+
id?: string;
|
|
84
|
+
metadata?: Record<string, any>;
|
|
85
|
+
}): Promise<T>;
|
|
86
|
+
/**
|
|
87
|
+
* Handle successful request
|
|
88
|
+
*/
|
|
89
|
+
private handleSuccess;
|
|
90
|
+
/**
|
|
91
|
+
* Handle failed request
|
|
92
|
+
*/
|
|
93
|
+
private handleFailure;
|
|
94
|
+
/**
|
|
95
|
+
* Handle request timeout
|
|
96
|
+
*/
|
|
97
|
+
private handleTimeout;
|
|
98
|
+
/**
|
|
99
|
+
* Handle fallback execution
|
|
100
|
+
*/
|
|
101
|
+
private handleFallback;
|
|
102
|
+
/**
|
|
103
|
+
* Check if circuit should be opened
|
|
104
|
+
*/
|
|
105
|
+
private shouldOpenCircuit;
|
|
106
|
+
/**
|
|
107
|
+
* Get recent requests within monitoring window
|
|
108
|
+
*/
|
|
109
|
+
private getRecentRequests;
|
|
110
|
+
/**
|
|
111
|
+
* Track request in monitoring window
|
|
112
|
+
*/
|
|
113
|
+
private trackRequest;
|
|
114
|
+
/**
|
|
115
|
+
* Transition to OPEN state
|
|
116
|
+
*/
|
|
117
|
+
private transitionToOpen;
|
|
118
|
+
/**
|
|
119
|
+
* Transition to HALF_OPEN state
|
|
120
|
+
*/
|
|
121
|
+
private transitionToHalfOpen;
|
|
122
|
+
/**
|
|
123
|
+
* Transition to CLOSED state
|
|
124
|
+
*/
|
|
125
|
+
private transitionToClosed;
|
|
126
|
+
/**
|
|
127
|
+
* Add fallback strategy
|
|
128
|
+
*/
|
|
129
|
+
addFallbackStrategy(strategy: FallbackStrategy): void;
|
|
130
|
+
/**
|
|
131
|
+
* Remove fallback strategy
|
|
132
|
+
*/
|
|
133
|
+
removeFallbackStrategy(strategyClass: any): void;
|
|
134
|
+
/**
|
|
135
|
+
* Get current circuit breaker statistics
|
|
136
|
+
*/
|
|
137
|
+
getStats(): CircuitStats;
|
|
138
|
+
/**
|
|
139
|
+
* Force circuit state change (for testing)
|
|
140
|
+
*/
|
|
141
|
+
forceState(state: CircuitState): void;
|
|
142
|
+
/**
|
|
143
|
+
* Reset circuit breaker to initial state
|
|
144
|
+
*/
|
|
145
|
+
reset(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Cleanup and shutdown
|
|
148
|
+
*/
|
|
149
|
+
shutdown(): void;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Default fallback strategies
|
|
153
|
+
*/
|
|
154
|
+
/**
|
|
155
|
+
* Cache fallback - return cached response if available
|
|
156
|
+
*/
|
|
157
|
+
export declare class CachedResponseFallback implements FallbackStrategy {
|
|
158
|
+
private cache;
|
|
159
|
+
priority: number;
|
|
160
|
+
constructor(cache: Map<string, any>);
|
|
161
|
+
canHandle(_error: Error): boolean;
|
|
162
|
+
execute(context: RequestContext, _error: Error): Promise<any>;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Degraded service fallback - return simplified response
|
|
166
|
+
*/
|
|
167
|
+
export declare class DegradedServiceFallback implements FallbackStrategy {
|
|
168
|
+
private degradedResponse;
|
|
169
|
+
priority: number;
|
|
170
|
+
constructor(degradedResponse: any);
|
|
171
|
+
canHandle(_error: Error): boolean;
|
|
172
|
+
execute(context: RequestContext, error: Error): Promise<any>;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Retry with delay fallback
|
|
176
|
+
*/
|
|
177
|
+
export declare class RetryFallback implements FallbackStrategy {
|
|
178
|
+
private retryFn;
|
|
179
|
+
private maxRetries;
|
|
180
|
+
private delay;
|
|
181
|
+
priority: number;
|
|
182
|
+
constructor(retryFn: () => Promise<any>, maxRetries?: number, delay?: number);
|
|
183
|
+
canHandle(error: Error): boolean;
|
|
184
|
+
execute(context: RequestContext, _error: Error): Promise<any>;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=circuit-breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/streaming/circuit-breaker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { logger } from '../logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Circuit breaker states
|
|
5
|
+
*/
|
|
6
|
+
export var CircuitState;
|
|
7
|
+
(function (CircuitState) {
|
|
8
|
+
CircuitState["CLOSED"] = "closed";
|
|
9
|
+
CircuitState["OPEN"] = "open";
|
|
10
|
+
CircuitState["HALF_OPEN"] = "half_open"; // Testing if service has recovered
|
|
11
|
+
})(CircuitState || (CircuitState = {}));
|
|
12
|
+
/**
|
|
13
|
+
* Circuit breaker with intelligent fallback handling
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Automatic failure detection and recovery
|
|
17
|
+
* - Configurable thresholds and timeouts
|
|
18
|
+
* - Multiple fallback strategies with priority
|
|
19
|
+
* - Real-time statistics and monitoring
|
|
20
|
+
* - Graceful degradation patterns
|
|
21
|
+
* - Request queuing during recovery
|
|
22
|
+
*/
|
|
23
|
+
export class CircuitBreaker extends EventEmitter {
|
|
24
|
+
config;
|
|
25
|
+
name;
|
|
26
|
+
state = CircuitState.CLOSED;
|
|
27
|
+
failures = 0;
|
|
28
|
+
successes = 0;
|
|
29
|
+
totalRequests = 0;
|
|
30
|
+
lastFailureTime;
|
|
31
|
+
lastSuccessTime;
|
|
32
|
+
recoveryTimer;
|
|
33
|
+
pendingRequests = new Map();
|
|
34
|
+
fallbackStrategies = [];
|
|
35
|
+
responseTimesWindow = [];
|
|
36
|
+
requestTimesWindow = [];
|
|
37
|
+
constructor(config, name = 'CircuitBreaker') {
|
|
38
|
+
super();
|
|
39
|
+
this.config = config;
|
|
40
|
+
this.name = name;
|
|
41
|
+
logger.info(`🔌 Circuit breaker '${this.name}' initialized`, {
|
|
42
|
+
failureThreshold: config.failureThreshold,
|
|
43
|
+
recoveryTimeout: config.recoveryTimeout,
|
|
44
|
+
timeout: config.timeout
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Execute function with circuit breaker protection
|
|
49
|
+
*/
|
|
50
|
+
async execute(fn, context) {
|
|
51
|
+
const requestId = context?.id || `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
52
|
+
const startTime = Date.now();
|
|
53
|
+
this.totalRequests++;
|
|
54
|
+
// Check circuit state
|
|
55
|
+
if (this.state === CircuitState.OPEN) {
|
|
56
|
+
const error = new Error(`Circuit breaker '${this.name}' is OPEN`);
|
|
57
|
+
this.emit('requestBlocked', { requestId, reason: 'circuit_open' });
|
|
58
|
+
return this.handleFallback(requestId, startTime, error);
|
|
59
|
+
}
|
|
60
|
+
// Create request context
|
|
61
|
+
const requestContext = {
|
|
62
|
+
id: requestId,
|
|
63
|
+
startTime,
|
|
64
|
+
timeout: setTimeout(() => {
|
|
65
|
+
this.handleTimeout(requestContext);
|
|
66
|
+
}, this.config.timeout),
|
|
67
|
+
resolve: () => { },
|
|
68
|
+
reject: () => { }
|
|
69
|
+
};
|
|
70
|
+
this.pendingRequests.set(requestId, requestContext);
|
|
71
|
+
try {
|
|
72
|
+
logger.debug(`🔌 Circuit breaker executing request ${requestId}`);
|
|
73
|
+
const result = await Promise.race([
|
|
74
|
+
fn(),
|
|
75
|
+
new Promise((_, reject) => {
|
|
76
|
+
requestContext.reject = reject;
|
|
77
|
+
})
|
|
78
|
+
]);
|
|
79
|
+
this.handleSuccess(requestContext);
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return this.handleFailure(requestContext, error);
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
clearTimeout(requestContext.timeout);
|
|
87
|
+
this.pendingRequests.delete(requestId);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Handle successful request
|
|
92
|
+
*/
|
|
93
|
+
handleSuccess(context) {
|
|
94
|
+
const responseTime = Date.now() - context.startTime;
|
|
95
|
+
this.successes++;
|
|
96
|
+
this.lastSuccessTime = Date.now();
|
|
97
|
+
// Track response time
|
|
98
|
+
this.responseTimesWindow.push(responseTime);
|
|
99
|
+
if (this.responseTimesWindow.length > 100) {
|
|
100
|
+
this.responseTimesWindow.shift();
|
|
101
|
+
}
|
|
102
|
+
// Track request in monitoring window
|
|
103
|
+
this.trackRequest(true);
|
|
104
|
+
logger.debug(`✅ Circuit breaker success: ${context.id} (${responseTime}ms)`);
|
|
105
|
+
// Handle state transitions
|
|
106
|
+
if (this.state === CircuitState.HALF_OPEN) {
|
|
107
|
+
if (this.successes >= this.config.successThreshold) {
|
|
108
|
+
this.transitionToClosed();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
this.emit('requestSuccess', {
|
|
112
|
+
requestId: context.id,
|
|
113
|
+
responseTime,
|
|
114
|
+
state: this.state
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Handle failed request
|
|
119
|
+
*/
|
|
120
|
+
async handleFailure(context, error) {
|
|
121
|
+
const responseTime = Date.now() - context.startTime;
|
|
122
|
+
this.failures++;
|
|
123
|
+
this.lastFailureTime = Date.now();
|
|
124
|
+
// Track request in monitoring window
|
|
125
|
+
this.trackRequest(false);
|
|
126
|
+
logger.warn(`❌ Circuit breaker failure: ${context.id} (${responseTime}ms) - ${error.message}`);
|
|
127
|
+
// Check if we should open the circuit
|
|
128
|
+
if (this.shouldOpenCircuit()) {
|
|
129
|
+
this.transitionToOpen();
|
|
130
|
+
}
|
|
131
|
+
this.emit('requestFailure', {
|
|
132
|
+
requestId: context.id,
|
|
133
|
+
error: error.message,
|
|
134
|
+
responseTime,
|
|
135
|
+
state: this.state
|
|
136
|
+
});
|
|
137
|
+
// Try fallback strategies
|
|
138
|
+
return this.handleFallback(context.id, context.startTime, error);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Handle request timeout
|
|
142
|
+
*/
|
|
143
|
+
handleTimeout(context) {
|
|
144
|
+
const error = new Error(`Request ${context.id} timed out after ${this.config.timeout}ms`);
|
|
145
|
+
context.reject(error);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Handle fallback execution
|
|
149
|
+
*/
|
|
150
|
+
async handleFallback(requestId, startTime, error) {
|
|
151
|
+
// Sort strategies by priority
|
|
152
|
+
const sortedStrategies = [...this.fallbackStrategies].sort((a, b) => a.priority - b.priority);
|
|
153
|
+
for (const strategy of sortedStrategies) {
|
|
154
|
+
if (strategy.canHandle(error)) {
|
|
155
|
+
try {
|
|
156
|
+
logger.info(`🔄 Executing fallback strategy for ${requestId}: ${strategy.constructor.name}`);
|
|
157
|
+
const result = await strategy.execute({
|
|
158
|
+
id: requestId,
|
|
159
|
+
startTime,
|
|
160
|
+
timeout: setTimeout(() => { }, 0), // Dummy timeout
|
|
161
|
+
resolve: () => { },
|
|
162
|
+
reject: () => { }
|
|
163
|
+
}, error);
|
|
164
|
+
this.emit('fallbackSuccess', {
|
|
165
|
+
requestId,
|
|
166
|
+
strategy: strategy.constructor.name,
|
|
167
|
+
originalError: error.message
|
|
168
|
+
});
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
catch (fallbackError) {
|
|
172
|
+
logger.warn(`Fallback strategy failed for ${requestId}:`, fallbackError);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// No fallback worked, throw original error
|
|
178
|
+
this.emit('fallbackExhausted', {
|
|
179
|
+
requestId,
|
|
180
|
+
originalError: error.message,
|
|
181
|
+
triedStrategies: sortedStrategies.length
|
|
182
|
+
});
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Check if circuit should be opened
|
|
187
|
+
*/
|
|
188
|
+
shouldOpenCircuit() {
|
|
189
|
+
if (this.state === CircuitState.OPEN) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
// Check failure threshold
|
|
193
|
+
if (this.failures >= this.config.failureThreshold) {
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
// Check failure rate within monitoring window
|
|
197
|
+
const recentRequests = this.getRecentRequests();
|
|
198
|
+
if (recentRequests.length >= this.config.minimumRequests) {
|
|
199
|
+
const recentFailures = recentRequests.filter(r => !r.success).length;
|
|
200
|
+
const failureRate = recentFailures / recentRequests.length;
|
|
201
|
+
// Open if failure rate > 50%
|
|
202
|
+
if (failureRate > 0.5) {
|
|
203
|
+
logger.warn(`📊 High failure rate detected: ${Math.round(failureRate * 100)}%`);
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get recent requests within monitoring window
|
|
211
|
+
*/
|
|
212
|
+
getRecentRequests() {
|
|
213
|
+
const cutoff = Date.now() - this.config.monitoringWindow;
|
|
214
|
+
return this.requestTimesWindow.filter(r => r.timestamp > cutoff);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Track request in monitoring window
|
|
218
|
+
*/
|
|
219
|
+
trackRequest(success) {
|
|
220
|
+
this.requestTimesWindow.push({
|
|
221
|
+
timestamp: Date.now(),
|
|
222
|
+
success
|
|
223
|
+
});
|
|
224
|
+
// Keep window size manageable
|
|
225
|
+
if (this.requestTimesWindow.length > 1000) {
|
|
226
|
+
this.requestTimesWindow.shift();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Transition to OPEN state
|
|
231
|
+
*/
|
|
232
|
+
transitionToOpen() {
|
|
233
|
+
if (this.state === CircuitState.OPEN) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
logger.warn(`🔴 Circuit breaker '${this.name}' opened (failures: ${this.failures})`);
|
|
237
|
+
this.state = CircuitState.OPEN;
|
|
238
|
+
this.successes = 0; // Reset success counter
|
|
239
|
+
// Set recovery timer
|
|
240
|
+
this.recoveryTimer = setTimeout(() => {
|
|
241
|
+
this.transitionToHalfOpen();
|
|
242
|
+
}, this.config.recoveryTimeout);
|
|
243
|
+
this.emit('stateChanged', {
|
|
244
|
+
state: this.state,
|
|
245
|
+
reason: 'failure_threshold_exceeded',
|
|
246
|
+
failures: this.failures
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Transition to HALF_OPEN state
|
|
251
|
+
*/
|
|
252
|
+
transitionToHalfOpen() {
|
|
253
|
+
logger.info(`🟡 Circuit breaker '${this.name}' half-open (testing recovery)`);
|
|
254
|
+
this.state = CircuitState.HALF_OPEN;
|
|
255
|
+
this.successes = 0; // Reset for testing
|
|
256
|
+
this.emit('stateChanged', {
|
|
257
|
+
state: this.state,
|
|
258
|
+
reason: 'recovery_timeout_reached'
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Transition to CLOSED state
|
|
263
|
+
*/
|
|
264
|
+
transitionToClosed() {
|
|
265
|
+
logger.info(`🟢 Circuit breaker '${this.name}' closed (recovered)`);
|
|
266
|
+
this.state = CircuitState.CLOSED;
|
|
267
|
+
this.failures = 0; // Reset failure counter
|
|
268
|
+
if (this.recoveryTimer) {
|
|
269
|
+
clearTimeout(this.recoveryTimer);
|
|
270
|
+
this.recoveryTimer = undefined;
|
|
271
|
+
}
|
|
272
|
+
this.emit('stateChanged', {
|
|
273
|
+
state: this.state,
|
|
274
|
+
reason: 'recovery_successful',
|
|
275
|
+
successes: this.successes
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Add fallback strategy
|
|
280
|
+
*/
|
|
281
|
+
addFallbackStrategy(strategy) {
|
|
282
|
+
this.fallbackStrategies.push(strategy);
|
|
283
|
+
this.fallbackStrategies.sort((a, b) => a.priority - b.priority);
|
|
284
|
+
logger.info(`📋 Added fallback strategy: ${strategy.constructor.name} (priority: ${strategy.priority})`);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Remove fallback strategy
|
|
288
|
+
*/
|
|
289
|
+
removeFallbackStrategy(strategyClass) {
|
|
290
|
+
const index = this.fallbackStrategies.findIndex(s => s instanceof strategyClass);
|
|
291
|
+
if (index >= 0) {
|
|
292
|
+
const removed = this.fallbackStrategies.splice(index, 1)[0];
|
|
293
|
+
logger.info(`🗑️ Removed fallback strategy: ${removed.constructor.name}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get current circuit breaker statistics
|
|
298
|
+
*/
|
|
299
|
+
getStats() {
|
|
300
|
+
const recentRequests = this.getRecentRequests();
|
|
301
|
+
const recentFailures = recentRequests.filter(r => !r.success).length;
|
|
302
|
+
const failureRate = recentRequests.length > 0
|
|
303
|
+
? recentFailures / recentRequests.length
|
|
304
|
+
: 0;
|
|
305
|
+
const averageResponseTime = this.responseTimesWindow.length > 0
|
|
306
|
+
? this.responseTimesWindow.reduce((sum, time) => sum + time, 0) / this.responseTimesWindow.length
|
|
307
|
+
: 0;
|
|
308
|
+
return {
|
|
309
|
+
state: this.state,
|
|
310
|
+
failures: this.failures,
|
|
311
|
+
successes: this.successes,
|
|
312
|
+
totalRequests: this.totalRequests,
|
|
313
|
+
lastFailureTime: this.lastFailureTime,
|
|
314
|
+
lastSuccessTime: this.lastSuccessTime,
|
|
315
|
+
uptime: this.lastSuccessTime ? Date.now() - this.lastSuccessTime : 0,
|
|
316
|
+
failureRate,
|
|
317
|
+
averageResponseTime
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Force circuit state change (for testing)
|
|
322
|
+
*/
|
|
323
|
+
forceState(state) {
|
|
324
|
+
logger.warn(`⚠️ Forcing circuit breaker '${this.name}' to ${state}`);
|
|
325
|
+
if (this.recoveryTimer) {
|
|
326
|
+
clearTimeout(this.recoveryTimer);
|
|
327
|
+
this.recoveryTimer = undefined;
|
|
328
|
+
}
|
|
329
|
+
this.state = state;
|
|
330
|
+
if (state === CircuitState.OPEN) {
|
|
331
|
+
this.recoveryTimer = setTimeout(() => {
|
|
332
|
+
this.transitionToHalfOpen();
|
|
333
|
+
}, this.config.recoveryTimeout);
|
|
334
|
+
}
|
|
335
|
+
this.emit('stateChanged', {
|
|
336
|
+
state: this.state,
|
|
337
|
+
reason: 'forced_state_change'
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Reset circuit breaker to initial state
|
|
342
|
+
*/
|
|
343
|
+
reset() {
|
|
344
|
+
logger.info(`🔄 Resetting circuit breaker '${this.name}'`);
|
|
345
|
+
if (this.recoveryTimer) {
|
|
346
|
+
clearTimeout(this.recoveryTimer);
|
|
347
|
+
this.recoveryTimer = undefined;
|
|
348
|
+
}
|
|
349
|
+
this.state = CircuitState.CLOSED;
|
|
350
|
+
this.failures = 0;
|
|
351
|
+
this.successes = 0;
|
|
352
|
+
this.totalRequests = 0;
|
|
353
|
+
this.lastFailureTime = undefined;
|
|
354
|
+
this.lastSuccessTime = undefined;
|
|
355
|
+
this.responseTimesWindow = [];
|
|
356
|
+
this.requestTimesWindow = [];
|
|
357
|
+
// Cancel pending requests
|
|
358
|
+
for (const [requestId, context] of this.pendingRequests) {
|
|
359
|
+
clearTimeout(context.timeout);
|
|
360
|
+
context.reject(new Error('Circuit breaker reset'));
|
|
361
|
+
}
|
|
362
|
+
this.pendingRequests.clear();
|
|
363
|
+
this.emit('reset');
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Cleanup and shutdown
|
|
367
|
+
*/
|
|
368
|
+
shutdown() {
|
|
369
|
+
logger.info(`🛑 Shutting down circuit breaker '${this.name}'`);
|
|
370
|
+
if (this.recoveryTimer) {
|
|
371
|
+
clearTimeout(this.recoveryTimer);
|
|
372
|
+
}
|
|
373
|
+
// Cancel all pending requests
|
|
374
|
+
for (const [requestId, context] of this.pendingRequests) {
|
|
375
|
+
clearTimeout(context.timeout);
|
|
376
|
+
context.reject(new Error('Circuit breaker shutdown'));
|
|
377
|
+
}
|
|
378
|
+
this.removeAllListeners();
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Default fallback strategies
|
|
383
|
+
*/
|
|
384
|
+
/**
|
|
385
|
+
* Cache fallback - return cached response if available
|
|
386
|
+
*/
|
|
387
|
+
export class CachedResponseFallback {
|
|
388
|
+
cache;
|
|
389
|
+
priority = 1;
|
|
390
|
+
constructor(cache) {
|
|
391
|
+
this.cache = cache;
|
|
392
|
+
}
|
|
393
|
+
canHandle(_error) {
|
|
394
|
+
return true; // Can handle any error if cache is available
|
|
395
|
+
}
|
|
396
|
+
async execute(context, _error) {
|
|
397
|
+
const cached = this.cache.get(context.id);
|
|
398
|
+
if (cached) {
|
|
399
|
+
logger.info(`📋 Using cached response for ${context.id}`);
|
|
400
|
+
return cached;
|
|
401
|
+
}
|
|
402
|
+
throw new Error('No cached response available');
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Degraded service fallback - return simplified response
|
|
407
|
+
*/
|
|
408
|
+
export class DegradedServiceFallback {
|
|
409
|
+
degradedResponse;
|
|
410
|
+
priority = 2;
|
|
411
|
+
constructor(degradedResponse) {
|
|
412
|
+
this.degradedResponse = degradedResponse;
|
|
413
|
+
}
|
|
414
|
+
canHandle(_error) {
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
async execute(context, error) {
|
|
418
|
+
logger.info(`🔻 Using degraded service response for ${context.id}`);
|
|
419
|
+
return {
|
|
420
|
+
...this.degradedResponse,
|
|
421
|
+
metadata: {
|
|
422
|
+
fallback: true,
|
|
423
|
+
originalError: error.message,
|
|
424
|
+
timestamp: Date.now()
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Retry with delay fallback
|
|
431
|
+
*/
|
|
432
|
+
export class RetryFallback {
|
|
433
|
+
retryFn;
|
|
434
|
+
maxRetries;
|
|
435
|
+
delay;
|
|
436
|
+
priority = 3;
|
|
437
|
+
constructor(retryFn, maxRetries = 3, delay = 1000) {
|
|
438
|
+
this.retryFn = retryFn;
|
|
439
|
+
this.maxRetries = maxRetries;
|
|
440
|
+
this.delay = delay;
|
|
441
|
+
}
|
|
442
|
+
canHandle(error) {
|
|
443
|
+
// Only retry on certain error types
|
|
444
|
+
return !error.message.includes('timeout') &&
|
|
445
|
+
!error.message.includes('validation');
|
|
446
|
+
}
|
|
447
|
+
async execute(context, _error) {
|
|
448
|
+
for (let i = 0; i < this.maxRetries; i++) {
|
|
449
|
+
try {
|
|
450
|
+
logger.info(`🔄 Retry attempt ${i + 1}/${this.maxRetries} for ${context.id}`);
|
|
451
|
+
await new Promise(resolve => setTimeout(resolve, this.delay * (i + 1)));
|
|
452
|
+
return await this.retryFn();
|
|
453
|
+
}
|
|
454
|
+
catch (retryError) {
|
|
455
|
+
if (i === this.maxRetries - 1) {
|
|
456
|
+
throw retryError;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
throw new Error('All retry attempts failed');
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
//# sourceMappingURL=circuit-breaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/streaming/circuit-breaker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAN,IAAY,YAIX;AAJD,WAAY,YAAY;IACtB,iCAAiB,CAAA;IACjB,6BAAa,CAAA;IACb,uCAAuB,CAAA,CAAC,mCAAmC;AAC7D,CAAC,EAJW,YAAY,KAAZ,YAAY,QAIvB;AAiDD;;;;;;;;;;GAUG;AACH,MAAM,OAAO,cAAe,SAAQ,YAAY;IAcpC;IACA;IAdF,KAAK,GAAiB,YAAY,CAAC,MAAM,CAAC;IAC1C,QAAQ,GAAG,CAAC,CAAC;IACb,SAAS,GAAG,CAAC,CAAC;IACd,aAAa,GAAG,CAAC,CAAC;IAClB,eAAe,CAAU;IACzB,eAAe,CAAU;IACzB,aAAa,CAAkB;IAC/B,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;IACpD,kBAAkB,GAAuB,EAAE,CAAC;IAC5C,mBAAmB,GAAa,EAAE,CAAC;IACnC,kBAAkB,GAA8C,EAAE,CAAC;IAE3E,YACU,MAA4B,EAC5B,OAAe,gBAAgB;QAEvC,KAAK,EAAE,CAAC;QAHA,WAAM,GAAN,MAAM,CAAsB;QAC5B,SAAI,GAAJ,IAAI,CAA2B;QAIvC,MAAM,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,IAAI,eAAe,EAAE;YAC3D,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CACX,EAAoB,EACpB,OAAyD;QAEzD,MAAM,SAAS,GAAG,OAAO,EAAE,EAAE,IAAI,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAChG,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,sBAAsB;QACtB,IAAI,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,IAAI,EAAE,CAAC;YACrC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,WAAW,CAAC,CAAC;YAClE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;YACnE,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;QAED,yBAAyB;QACzB,MAAM,cAAc,GAAmB;YACrC,EAAE,EAAE,SAAS;YACb,SAAS;YACT,OAAO,EAAE,UAAU,CAAC,GAAG,EAAE;gBACvB,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;YACrC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YACvB,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;YACjB,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;SACjB,CAAC;QAEF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAEpD,IAAI,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,wCAAwC,SAAS,EAAE,CAAC,CAAC;YAElE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;gBAChC,EAAE,EAAE;gBACJ,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;oBAC/B,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC;gBACjC,CAAC,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;YACnC,OAAO,MAAM,CAAC;QAEhB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,KAAc,CAAC,CAAC;QAC5D,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,OAAuB;QAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;QAEpD,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAElC,sBAAsB;QACtB,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,mBAAmB,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC1C,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;QACnC,CAAC;QAED,qCAAqC;QACrC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAExB,MAAM,CAAC,KAAK,CAAC,8BAA8B,OAAO,CAAC,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC;QAE7E,2BAA2B;QAC3B,IAAI,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,SAAS,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBACnD,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAC1B,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,YAAY;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CAAC,OAAuB,EAAE,KAAY;QAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;QAEpD,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAElC,qCAAqC;QACrC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAEzB,MAAM,CAAC,IAAI,CAAC,8BAA8B,OAAO,CAAC,EAAE,KAAK,YAAY,SAAS,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAE/F,sCAAsC;QACtC,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YAC7B,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAC1B,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,YAAY;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;QAEH,0BAA0B;QAC1B,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,OAAuB;QAC3C,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,OAAO,CAAC,EAAE,oBAAoB,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;QAC1F,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAAC,SAAiB,EAAE,SAAiB,EAAE,KAAY;QAC7E,8BAA8B;QAC9B,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAE9F,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;YACxC,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,IAAI,CAAC;oBACH,MAAM,CAAC,IAAI,CAAC,sCAAsC,SAAS,KAAK,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;oBAE7F,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;wBACpC,EAAE,EAAE,SAAS;wBACb,SAAS;wBACT,OAAO,EAAE,UAAU,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC,CAAC,EAAE,gBAAgB;wBAClD,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;wBACjB,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;qBACjB,EAAE,KAAK,CAAC,CAAC;oBAEV,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;wBAC3B,SAAS;wBACT,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI;wBACnC,aAAa,EAAE,KAAK,CAAC,OAAO;qBAC7B,CAAC,CAAC;oBAEH,OAAO,MAAM,CAAC;gBAEhB,CAAC;gBAAC,OAAO,aAAa,EAAE,CAAC;oBACvB,MAAM,CAAC,IAAI,CAAC,gCAAgC,SAAS,GAAG,EAAE,aAAa,CAAC,CAAC;oBACzE,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;QAED,2CAA2C;QAC3C,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE;YAC7B,SAAS;YACT,aAAa,EAAE,KAAK,CAAC,OAAO;YAC5B,eAAe,EAAE,gBAAgB,CAAC,MAAM;SACzC,CAAC,CAAC;QAEH,MAAM,KAAK,CAAC;IACd,CAAC;IAED;;OAEG;IACK,iBAAiB;QACvB,IAAI,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,IAAI,EAAE,CAAC;YACrC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,0BAA0B;QAC1B,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,8CAA8C;QAC9C,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAChD,IAAI,cAAc,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;YACzD,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;YACrE,MAAM,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC;YAE3D,6BAA6B;YAC7B,IAAI,WAAW,GAAG,GAAG,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,kCAAkC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;gBAChF,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACK,iBAAiB;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC;QACzD,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,OAAgB;QACnC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;YAC3B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,OAAO;SACR,CAAC,CAAC;QAEH,8BAA8B;QAC9B,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;YAC1C,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;OAEG;IACK,gBAAgB;QACtB,IAAI,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,IAAI,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,IAAI,uBAAuB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAErF,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC;QAC/B,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,wBAAwB;QAE5C,qBAAqB;QACrB,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9B,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAEhC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YACxB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,4BAA4B;YACpC,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,oBAAoB;QAC1B,MAAM,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,IAAI,gCAAgC,CAAC,CAAC;QAE9E,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,oBAAoB;QAExC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YACxB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,0BAA0B;SACnC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,kBAAkB;QACxB,MAAM,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,IAAI,sBAAsB,CAAC,CAAC;QAEpE,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,wBAAwB;QAE3C,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YACxB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,qBAAqB;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,QAA0B;QAC5C,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAEhE,MAAM,CAAC,IAAI,CAAC,+BAA+B,QAAQ,CAAC,WAAW,CAAC,IAAI,eAAe,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC;IAC3G,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,aAAkB;QACvC,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,aAAa,CAAC,CAAC;QACjF,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,MAAM,CAAC,IAAI,CAAC,kCAAkC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAChD,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QACrE,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC;YAC3C,CAAC,CAAC,cAAc,GAAG,cAAc,CAAC,MAAM;YACxC,CAAC,CAAC,CAAC,CAAC;QAEN,MAAM,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC;YAC7D,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,mBAAmB,CAAC,MAAM;YACjG,CAAC,CAAC,CAAC,CAAC;QAEN,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YACpE,WAAW;YACX,mBAAmB;SACpB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,KAAmB;QAC5B,MAAM,CAAC,IAAI,CAAC,+BAA+B,IAAI,CAAC,IAAI,QAAQ,KAAK,EAAE,CAAC,CAAC;QAErE,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,IAAI,KAAK,KAAK,YAAY,CAAC,IAAI,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;gBACnC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9B,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YACxB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,qBAAqB;SAC9B,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK;QACH,MAAM,CAAC,IAAI,CAAC,iCAAiC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAE3D,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;QAC9B,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAE7B,0BAA0B;QAC1B,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACxD,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAE7B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,CAAC,IAAI,CAAC,qCAAqC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAE/D,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;QAED,8BAA8B;QAC9B,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACxD,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AAEH;;GAEG;AACH,MAAM,OAAO,sBAAsB;IAGb;IAFpB,QAAQ,GAAG,CAAC,CAAC;IAEb,YAAoB,KAAuB;QAAvB,UAAK,GAAL,KAAK,CAAkB;IAAG,CAAC;IAE/C,SAAS,CAAC,MAAa;QACrB,OAAO,IAAI,CAAC,CAAC,6CAA6C;IAC5D,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAuB,EAAE,MAAa;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,gCAAgC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;YAC1D,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,uBAAuB;IAGd;IAFpB,QAAQ,GAAG,CAAC,CAAC;IAEb,YAAoB,gBAAqB;QAArB,qBAAgB,GAAhB,gBAAgB,CAAK;IAAG,CAAC;IAE7C,SAAS,CAAC,MAAa;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAuB,EAAE,KAAY;QACjD,MAAM,CAAC,IAAI,CAAC,0CAA0C,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QACpE,OAAO;YACL,GAAG,IAAI,CAAC,gBAAgB;YACxB,QAAQ,EAAE;gBACR,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,KAAK,CAAC,OAAO;gBAC5B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB;SACF,CAAC;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAa;IAId;IACA;IACA;IALV,QAAQ,GAAG,CAAC,CAAC;IAEb,YACU,OAA2B,EAC3B,aAAqB,CAAC,EACtB,QAAgB,IAAI;QAFpB,YAAO,GAAP,OAAO,CAAoB;QAC3B,eAAU,GAAV,UAAU,CAAY;QACtB,UAAK,GAAL,KAAK,CAAe;IAC3B,CAAC;IAEJ,SAAS,CAAC,KAAY;QACpB,oCAAoC;QACpC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;YAClC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAuB,EAAE,MAAa;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,QAAQ,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;gBAE9E,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxE,OAAO,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YAE9B,CAAC;YAAC,OAAO,UAAU,EAAE,CAAC;gBACpB,IAAI,CAAC,KAAK,IAAI,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;oBAC9B,MAAM,UAAU,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;CACF"}
|