claude-flow-novice 2.0.3 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli/commands/guidance.js +487 -668
- package/dist/src/cli/commands/index-validate.js +18 -29
- package/dist/src/cli/commands/mcp-troubleshoot.js +230 -282
- package/dist/src/cli/commands/neural-goal-init.js +92 -125
- package/dist/src/cli/commands/swarm-exec.js +317 -393
- package/dist/src/cli/commands/swarm.js +1 -1
- package/dist/src/cli/commands/validate-framework.js +983 -1100
- package/dist/src/cli/commands/validate.js +144 -223
- package/dist/src/cli/simple-commands/__tests__/agent.test.js +265 -277
- package/dist/src/cli/simple-commands/__tests__/memory.test.js +6 -7
- package/dist/src/cli/simple-commands/__tests__/swarm.test.js +373 -356
- package/dist/src/cli/simple-commands/__tests__/task.test.js +6 -7
- package/dist/src/cli/simple-commands/agent.js +157 -193
- package/dist/src/cli/simple-commands/analysis.js +336 -446
- package/dist/src/cli/simple-commands/automation-executor.js +1095 -1339
- package/dist/src/cli/simple-commands/automation.js +481 -469
- package/dist/src/cli/simple-commands/batch-manager.js +261 -313
- package/dist/src/cli/simple-commands/claude-telemetry.js +241 -267
- package/dist/src/cli/simple-commands/claude-track.js +68 -90
- package/dist/src/cli/simple-commands/concurrent-display.js +266 -320
- package/dist/src/cli/simple-commands/config.js +245 -290
- package/dist/src/cli/simple-commands/coordination.js +182 -234
- package/dist/src/cli/simple-commands/enhanced-ui-views.js +812 -615
- package/dist/src/cli/simple-commands/enhanced-webui-complete.js +922 -981
- package/dist/src/cli/simple-commands/fix-hook-variables.js +274 -294
- package/dist/src/cli/simple-commands/github/gh-coordinator.js +378 -457
- package/dist/src/cli/simple-commands/github/github-api.js +535 -574
- package/dist/src/cli/simple-commands/github/init.js +276 -303
- package/dist/src/cli/simple-commands/github.js +222 -247
- package/dist/src/cli/simple-commands/goal.js +51 -63
- package/dist/src/cli/simple-commands/hive-mind/auto-save-middleware.js +208 -278
- package/dist/src/cli/simple-commands/hive-mind/communication.js +601 -696
- package/dist/src/cli/simple-commands/hive-mind/core.js +907 -979
- package/dist/src/cli/simple-commands/hive-mind/db-optimizer.js +406 -655
- package/dist/src/cli/simple-commands/hive-mind/mcp-wrapper.js +1125 -1245
- package/dist/src/cli/simple-commands/hive-mind/memory.js +854 -1090
- package/dist/src/cli/simple-commands/hive-mind/performance-optimizer.js +459 -574
- package/dist/src/cli/simple-commands/hive-mind/performance-test.js +263 -347
- package/dist/src/cli/simple-commands/hive-mind/queen.js +727 -768
- package/dist/src/cli/simple-commands/hive-mind/session-manager.js +745 -1049
- package/dist/src/cli/simple-commands/hive-mind-optimize.js +227 -283
- package/dist/src/cli/simple-commands/hive-mind-wizard.js +174 -217
- package/dist/src/cli/simple-commands/hive-mind.js +1842 -2283
- package/dist/src/cli/simple-commands/hive.js +90 -79
- package/dist/src/cli/simple-commands/hook-safety.js +431 -521
- package/dist/src/cli/simple-commands/hooks/session-start-soul.js +203 -254
- package/dist/src/cli/simple-commands/hooks.js +1064 -1204
- package/dist/src/cli/simple-commands/init/agent-copier.js +294 -319
- package/dist/src/cli/simple-commands/init/batch-init.js +496 -562
- package/dist/src/cli/simple-commands/init/claude-commands/claude-flow-commands.js +13 -19
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-claude-flow-commands.js +13 -19
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-slash-commands.js +61 -88
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-sparc-commands.js +125 -150
- package/dist/src/cli/simple-commands/init/claude-commands/slash-commands.js +42 -49
- package/dist/src/cli/simple-commands/init/claude-commands/sparc-commands.js +43 -61
- package/dist/src/cli/simple-commands/init/copy-revised-templates.js +141 -147
- package/dist/src/cli/simple-commands/init/executable-wrapper.js +31 -44
- package/dist/src/cli/simple-commands/init/gitignore-updater.js +64 -90
- package/dist/src/cli/simple-commands/init/help.js +104 -107
- package/dist/src/cli/simple-commands/init/hive-mind-init.js +509 -528
- package/dist/src/cli/simple-commands/init/index.js +1510 -1759
- package/dist/src/cli/simple-commands/init/performance-monitor.js +234 -317
- package/dist/src/cli/simple-commands/init/rollback/backup-manager.js +441 -504
- package/dist/src/cli/simple-commands/init/rollback/index.js +289 -364
- package/dist/src/cli/simple-commands/init/rollback/recovery-manager.js +652 -728
- package/dist/src/cli/simple-commands/init/rollback/rollback-executor.js +416 -481
- package/dist/src/cli/simple-commands/init/rollback/state-tracker.js +369 -448
- package/dist/src/cli/simple-commands/init/sparc/roo-readme.js +1 -2
- package/dist/src/cli/simple-commands/init/sparc/roomodes-config.js +122 -99
- package/dist/src/cli/simple-commands/init/sparc/workflows.js +32 -37
- package/dist/src/cli/simple-commands/init/sparc-structure.js +55 -62
- package/dist/src/cli/simple-commands/init/template-copier.js +421 -533
- package/dist/src/cli/simple-commands/init/templates/coordination-md.js +3 -6
- package/dist/src/cli/simple-commands/init/templates/enhanced-templates.js +344 -318
- package/dist/src/cli/simple-commands/init/templates/github-safe-enhanced.js +173 -218
- package/dist/src/cli/simple-commands/init/templates/github-safe.js +65 -75
- package/dist/src/cli/simple-commands/init/templates/memory-bank-md.js +3 -6
- package/dist/src/cli/simple-commands/init/templates/readme-files.js +2 -4
- package/dist/src/cli/simple-commands/init/templates/safe-hook-patterns.js +187 -230
- package/dist/src/cli/simple-commands/init/templates/sparc-modes.js +53 -80
- package/dist/src/cli/simple-commands/init/templates/verification-claude-md.js +101 -85
- package/dist/src/cli/simple-commands/init/validation/config-validator.js +283 -330
- package/dist/src/cli/simple-commands/init/validation/health-checker.js +495 -561
- package/dist/src/cli/simple-commands/init/validation/index.js +302 -358
- package/dist/src/cli/simple-commands/init/validation/mode-validator.js +308 -359
- package/dist/src/cli/simple-commands/init/validation/post-init-validator.js +389 -366
- package/dist/src/cli/simple-commands/init/validation/pre-init-validator.js +270 -268
- package/dist/src/cli/simple-commands/init/validation/test-runner.js +427 -447
- package/dist/src/cli/simple-commands/init.js +1 -2
- package/dist/src/cli/simple-commands/mcp-health.js +131 -158
- package/dist/src/cli/simple-commands/mcp-integration-layer.js +533 -634
- package/dist/src/cli/simple-commands/mcp.js +345 -400
- package/dist/src/cli/simple-commands/memory-consolidation.js +426 -537
- package/dist/src/cli/simple-commands/memory.js +247 -311
- package/dist/src/cli/simple-commands/migrate-hooks.js +39 -46
- package/dist/src/cli/simple-commands/monitor.js +294 -363
- package/dist/src/cli/simple-commands/neural.js +51 -65
- package/dist/src/cli/simple-commands/pair-autofix-only.js +538 -662
- package/dist/src/cli/simple-commands/pair-basic.js +528 -656
- package/dist/src/cli/simple-commands/pair-old.js +430 -543
- package/dist/src/cli/simple-commands/pair-working.js +615 -751
- package/dist/src/cli/simple-commands/pair.js +615 -751
- package/dist/src/cli/simple-commands/performance-hooks.js +83 -111
- package/dist/src/cli/simple-commands/performance-metrics.js +348 -433
- package/dist/src/cli/simple-commands/process-ui-enhanced.js +708 -787
- package/dist/src/cli/simple-commands/process-ui.js +230 -254
- package/dist/src/cli/simple-commands/realtime-update-system.js +525 -611
- package/dist/src/cli/simple-commands/sparc/architecture.js +1704 -1530
- package/dist/src/cli/simple-commands/sparc/commands.js +438 -516
- package/dist/src/cli/simple-commands/sparc/completion.js +1224 -1481
- package/dist/src/cli/simple-commands/sparc/coordinator.js +913 -978
- package/dist/src/cli/simple-commands/sparc/index.js +241 -298
- package/dist/src/cli/simple-commands/sparc/phase-base.js +314 -390
- package/dist/src/cli/simple-commands/sparc/pseudocode.js +965 -869
- package/dist/src/cli/simple-commands/sparc/refinement.js +980 -1273
- package/dist/src/cli/simple-commands/sparc/specification.js +559 -645
- package/dist/src/cli/simple-commands/sparc-modes/architect.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/ask.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/code.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/debug.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/devops.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/docs-writer.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/generic.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/index.js +47 -55
- package/dist/src/cli/simple-commands/sparc-modes/integration.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/mcp.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/monitoring.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/optimization.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/security-review.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/sparc-orchestrator.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/spec-pseudocode.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/supabase-admin.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/swarm.js +101 -87
- package/dist/src/cli/simple-commands/sparc-modes/tdd.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/tutorial.js +1 -1
- package/dist/src/cli/simple-commands/sparc.js +465 -493
- package/dist/src/cli/simple-commands/start-ui.js +108 -132
- package/dist/src/cli/simple-commands/start-wrapper.js +240 -268
- package/dist/src/cli/simple-commands/start.js +1 -1
- package/dist/src/cli/simple-commands/status.js +254 -275
- package/dist/src/cli/simple-commands/stream-chain-clean.js +128 -171
- package/dist/src/cli/simple-commands/stream-chain-fixed.js +61 -82
- package/dist/src/cli/simple-commands/stream-chain-real.js +267 -331
- package/dist/src/cli/simple-commands/stream-chain-working.js +211 -263
- package/dist/src/cli/simple-commands/stream-chain.js +260 -318
- package/dist/src/cli/simple-commands/stream-processor.js +290 -315
- package/dist/src/cli/simple-commands/swarm-executor.js +189 -222
- package/dist/src/cli/simple-commands/swarm-metrics-integration.js +208 -300
- package/dist/src/cli/simple-commands/swarm-ui.js +623 -703
- package/dist/src/cli/simple-commands/swarm-webui-integration.js +258 -286
- package/dist/src/cli/simple-commands/swarm.js +887 -1082
- package/dist/src/cli/simple-commands/task.js +161 -206
- package/dist/src/cli/simple-commands/timestamp-fix.js +59 -89
- package/dist/src/cli/simple-commands/token-tracker.js +258 -316
- package/dist/src/cli/simple-commands/tool-execution-framework.js +433 -519
- package/dist/src/cli/simple-commands/train-and-stream.js +275 -331
- package/dist/src/cli/simple-commands/training-pipeline.js +619 -725
- package/dist/src/cli/simple-commands/training.js +170 -227
- package/dist/src/cli/simple-commands/verification-hooks.js +261 -284
- package/dist/src/cli/simple-commands/verification-integration.js +389 -417
- package/dist/src/cli/simple-commands/verification-training-integration.js +486 -606
- package/dist/src/cli/simple-commands/verification.js +493 -513
- package/dist/src/cli/simple-commands/web-server.js +766 -836
- package/dist/src/cli/simple-commands/webui-validator.js +106 -124
- package/dist/src/coordination/event-bus/demo-wasm-integration.js +212 -251
- package/dist/src/coordination/event-bus/qe-event-bus.js +608 -748
- package/dist/src/coordination/event-bus/qe-event-bus.test.js +379 -454
- package/dist/src/coordination/iteration-tracker.js +363 -454
- package/dist/src/enterprise/analytics-manager.js +1135 -0
- package/dist/src/enterprise/audit-manager.js +1115 -0
- package/dist/src/enterprise/cloud-manager.js +891 -0
- package/dist/src/enterprise/deployment-manager.js +966 -0
- package/dist/src/enterprise/index.js +6 -0
- package/dist/src/enterprise/project-manager.js +584 -0
- package/dist/src/enterprise/security-manager.js +991 -0
- package/dist/src/index.js +1 -1
- package/dist/src/mcp/DEPRECATED.js +46 -60
- package/dist/src/mcp/fixes/mcp-error-fixes.js +115 -134
- package/dist/src/mcp/implementations/agent-tracker.js +114 -128
- package/dist/src/mcp/implementations/daa-tools.js +292 -350
- package/dist/src/mcp/implementations/workflow-tools.js +329 -361
- package/dist/src/mcp/mcp-config-manager.js +1183 -1331
- package/dist/src/mcp/mcp-server-novice-simplified.js +11 -17
- package/dist/src/mcp/mcp-server-novice.js +11 -17
- package/dist/src/mcp/mcp-server-sdk.js +11 -17
- package/dist/src/mcp/mcp-server.js +1620 -1484
- package/dist/src/mcp/ruv-swarm-wrapper.js +209 -239
- package/dist/src/memory/advanced-serializer.js +609 -589
- package/dist/src/memory/enhanced-examples.js +220 -305
- package/dist/src/memory/enhanced-memory.js +295 -336
- package/dist/src/memory/enhanced-session-serializer.js +408 -492
- package/dist/src/memory/fallback-memory-system.js +900 -1021
- package/dist/src/memory/fallback-store.js +93 -131
- package/dist/src/memory/high-performance-serialization.js +592 -730
- package/dist/src/memory/in-memory-store.js +161 -213
- package/dist/src/memory/index.js +123 -157
- package/dist/src/memory/lock-free-structures.js +578 -764
- package/dist/src/memory/memory-mapped-persistence.js +585 -766
- package/dist/src/memory/memory-pressure-manager.js +569 -707
- package/dist/src/memory/migration.js +358 -445
- package/dist/src/memory/shared-memory.js +641 -768
- package/dist/src/memory/sqlite-store.js +245 -325
- package/dist/src/memory/sqlite-wrapper.js +122 -151
- package/dist/src/memory/swarm-memory.js +470 -603
- package/dist/src/memory/test-example.js +126 -134
- package/dist/src/memory/ultra-fast-memory-store.js +622 -821
- package/dist/src/memory/unified-memory-manager.js +356 -437
- package/dist/src/migration/index.js +92 -0
- package/dist/src/migration/logger.js +121 -0
- package/dist/src/migration/migration-analyzer.js +268 -0
- package/dist/src/migration/migration-runner.js +522 -0
- package/dist/src/migration/migration-validator.js +285 -0
- package/dist/src/migration/progress-reporter.js +150 -0
- package/dist/src/migration/rollback-manager.js +321 -0
- package/dist/src/migration/tests/migration-system.test.js +7 -0
- package/dist/src/migration/types.js +3 -0
- package/dist/src/swarm/CodeRefactoringSwarm.js +777 -952
- package/dist/src/swarm/__tests__/integration.test.js +227 -0
- package/dist/src/swarm/__tests__/prompt-copier.test.js +344 -0
- package/dist/src/swarm/advanced-orchestrator.js +1095 -0
- package/dist/src/swarm/claude-code-interface.js +961 -0
- package/dist/src/swarm/claude-flow-executor.js +229 -0
- package/dist/src/swarm/consensus-coordinator.js +475 -0
- package/dist/src/swarm/coordinator.js +2993 -0
- package/dist/src/swarm/direct-executor.js +1180 -0
- package/dist/src/swarm/error-recovery/advanced-error-detection.js +691 -0
- package/dist/src/swarm/error-recovery/automated-recovery-workflows.js +998 -0
- package/dist/src/swarm/error-recovery/error-recovery-coordinator.js +1197 -0
- package/dist/src/swarm/error-recovery/recovery-monitoring.js +772 -0
- package/dist/src/swarm/error-recovery/resilience-architecture.js +714 -0
- package/dist/src/swarm/error-recovery/self-healing-mechanisms.js +1319 -0
- package/dist/src/swarm/error-recovery/test-error-recovery-effectiveness.js +808 -0
- package/dist/src/swarm/executor-v2.js +322 -0
- package/dist/src/swarm/executor.js +815 -0
- package/dist/src/swarm/hive-mind-integration.js +703 -0
- package/dist/src/swarm/index.js +41 -0
- package/dist/src/swarm/json-output-aggregator.js +267 -0
- package/dist/src/swarm/large-scale-coordinator.js +542 -0
- package/dist/src/swarm/mcp-integration-wrapper.js +628 -0
- package/dist/src/swarm/memory.js +1117 -0
- package/dist/src/swarm/optimizations/__tests__/optimization.test.js +348 -0
- package/dist/src/swarm/optimizations/async-file-manager.js +285 -0
- package/dist/src/swarm/optimizations/circular-buffer.js +162 -0
- package/dist/src/swarm/optimizations/connection-pool.js +244 -0
- package/dist/src/swarm/optimizations/index.js +28 -0
- package/dist/src/swarm/optimizations/optimized-executor.js +320 -0
- package/dist/src/swarm/optimizations/ttl-map.js +234 -0
- package/dist/src/swarm/prompt-cli.js +200 -0
- package/dist/src/swarm/prompt-copier-enhanced.js +202 -0
- package/dist/src/swarm/prompt-copier.js +381 -0
- package/dist/src/swarm/prompt-manager.js +295 -0
- package/dist/src/swarm/prompt-utils.js +310 -0
- package/dist/src/swarm/result-aggregator.js +718 -0
- package/dist/src/swarm/sparc-executor.js +1568 -0
- package/dist/src/swarm/strategies/auto.js +758 -0
- package/dist/src/swarm/strategies/base.js +128 -0
- package/dist/src/swarm/strategies/research.js +914 -0
- package/dist/src/swarm/strategies/strategy-metrics-patch.js +2 -0
- package/dist/src/swarm/types.js +52 -0
- package/dist/src/swarm/workers/copy-worker.js +56 -0
- package/dist/src/utils/__tests__/github-cli-safety-wrapper.test.js +332 -400
- package/dist/src/utils/github-cli-safe.js +56 -64
- package/dist/src/utils/github-cli-safety-wrapper.js +451 -546
- package/dist/src/utils/npx-isolated-cache.js +104 -119
- package/dist/src/utils/preference-manager.js +622 -652
- package/dist/src/utils/timezone-utils.js +86 -105
- package/dist/src/validators/epic-config-schema.js +214 -0
- package/dist/src/validators/index.js +10 -0
- package/dist/src/validators/swarm-init-validator.js +259 -0
- package/dist/src/validators/todowrite-batching-validator.js +215 -0
- package/dist/src/validators/todowrite-integration.js +187 -0
- package/package.json +2 -2
|
@@ -0,0 +1,714 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resilience Architecture
|
|
3
|
+
* Circuit breaker patterns, failover mechanisms, and disaster recovery procedures
|
|
4
|
+
*/ function _define_property(obj, key, value) {
|
|
5
|
+
if (key in obj) {
|
|
6
|
+
Object.defineProperty(obj, key, {
|
|
7
|
+
value: value,
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true
|
|
11
|
+
});
|
|
12
|
+
} else {
|
|
13
|
+
obj[key] = value;
|
|
14
|
+
}
|
|
15
|
+
return obj;
|
|
16
|
+
}
|
|
17
|
+
import { EventEmitter } from "node:events";
|
|
18
|
+
import { createClient } from "redis";
|
|
19
|
+
export var CircuitState = /*#__PURE__*/ function(CircuitState) {
|
|
20
|
+
CircuitState["CLOSED"] = "closed";
|
|
21
|
+
CircuitState["OPEN"] = "open";
|
|
22
|
+
CircuitState["HALF_OPEN"] = "half_open"; // Testing if service has recovered
|
|
23
|
+
return CircuitState;
|
|
24
|
+
}({});
|
|
25
|
+
export class ResilienceArchitecture extends EventEmitter {
|
|
26
|
+
async start() {
|
|
27
|
+
if (this.isRunning) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
await this.redis.connect();
|
|
32
|
+
// Initialize circuit breakers
|
|
33
|
+
for (const cbConfig of this.config.circuitBreakers){
|
|
34
|
+
const circuitBreaker = new CircuitBreaker(cbConfig, this.logger);
|
|
35
|
+
this.circuitBreakers.set(cbConfig.name, circuitBreaker);
|
|
36
|
+
circuitBreaker.on('stateChange', (state)=>{
|
|
37
|
+
this.emit('circuitBreakerStateChange', {
|
|
38
|
+
name: cbConfig.name,
|
|
39
|
+
state
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// Initialize failover managers
|
|
44
|
+
for (const foConfig of this.config.failover){
|
|
45
|
+
const failoverManager = new FailoverManager(foConfig, this.logger, this.redis);
|
|
46
|
+
this.failoverManagers.set(foConfig.primary.id, failoverManager);
|
|
47
|
+
failoverManager.on('failover', (state)=>{
|
|
48
|
+
this.emit('failover', state);
|
|
49
|
+
});
|
|
50
|
+
failoverManager.on('failback', (state)=>{
|
|
51
|
+
this.emit('failback', state);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
// Start subsystems
|
|
55
|
+
await this.healthMonitor.start();
|
|
56
|
+
await this.disasterRecovery.start();
|
|
57
|
+
this.isRunning = true;
|
|
58
|
+
this.logger.info('Resilience architecture started', {
|
|
59
|
+
circuitBreakers: this.circuitBreakers.size,
|
|
60
|
+
failoverManagers: this.failoverManagers.size
|
|
61
|
+
});
|
|
62
|
+
this.emit('started');
|
|
63
|
+
} catch (error) {
|
|
64
|
+
this.logger.error('Failed to start resilience architecture', {
|
|
65
|
+
error
|
|
66
|
+
});
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async stop() {
|
|
71
|
+
if (!this.isRunning) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.isRunning = false;
|
|
75
|
+
await this.healthMonitor.stop();
|
|
76
|
+
await this.disasterRecovery.stop();
|
|
77
|
+
for (const circuitBreaker of this.circuitBreakers.values()){
|
|
78
|
+
circuitBreaker.destroy();
|
|
79
|
+
}
|
|
80
|
+
for (const failoverManager of this.failoverManagers.values()){
|
|
81
|
+
await failoverManager.stop();
|
|
82
|
+
}
|
|
83
|
+
await this.redis.disconnect();
|
|
84
|
+
this.emit('stopped');
|
|
85
|
+
this.logger.info('Resilience architecture stopped');
|
|
86
|
+
}
|
|
87
|
+
async executeWithResilience(serviceName, operation, options = {}) {
|
|
88
|
+
const circuitBreaker = this.circuitBreakers.get(serviceName);
|
|
89
|
+
const failoverManager = this.failoverManagers.get(serviceName);
|
|
90
|
+
if (!circuitBreaker && !failoverManager) {
|
|
91
|
+
// No resilience mechanisms configured, execute directly
|
|
92
|
+
return await this.executeWithTimeout(operation, options.timeout);
|
|
93
|
+
}
|
|
94
|
+
// Apply rate limiting
|
|
95
|
+
await this.rateLimiter.acquire();
|
|
96
|
+
// Apply bulkhead pattern
|
|
97
|
+
return await this.bulkheadManager.execute(async ()=>{
|
|
98
|
+
// Try circuit breaker first
|
|
99
|
+
if (circuitBreaker) {
|
|
100
|
+
try {
|
|
101
|
+
return await circuitBreaker.execute(operation, options.timeout);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
this.logger.warn('Circuit breaker rejected call', {
|
|
104
|
+
serviceName,
|
|
105
|
+
error: error instanceof Error ? error.message : String(error)
|
|
106
|
+
});
|
|
107
|
+
if (options.fallback) {
|
|
108
|
+
return await options.fallback();
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Try failover manager
|
|
114
|
+
if (failoverManager) {
|
|
115
|
+
return await failoverManager.execute(operation, options);
|
|
116
|
+
}
|
|
117
|
+
return await this.executeWithTimeout(operation, options.timeout);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async executeWithTimeout(operation, timeoutMs = 30000) {
|
|
121
|
+
return new Promise((resolve, reject)=>{
|
|
122
|
+
const timer = setTimeout(()=>{
|
|
123
|
+
reject(new Error(`Operation timed out after ${timeoutMs}ms`));
|
|
124
|
+
}, timeoutMs);
|
|
125
|
+
operation().then((result)=>{
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
resolve(result);
|
|
128
|
+
}).catch((error)=>{
|
|
129
|
+
clearTimeout(timer);
|
|
130
|
+
reject(error);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
async getCircuitBreakerStatus(name) {
|
|
135
|
+
const circuitBreaker = this.circuitBreakers.get(name);
|
|
136
|
+
return circuitBreaker ? circuitBreaker.getMetrics() : null;
|
|
137
|
+
}
|
|
138
|
+
async getFailoverStatus(serviceId) {
|
|
139
|
+
const failoverManager = this.failoverManagers.get(serviceId);
|
|
140
|
+
return failoverManager ? failoverManager.getState() : null;
|
|
141
|
+
}
|
|
142
|
+
async triggerEmergencyProcedure(procedureId, context = {}) {
|
|
143
|
+
return await this.disasterRecovery.executeProcedure(procedureId, context);
|
|
144
|
+
}
|
|
145
|
+
async manualFailover(serviceId, targetEndpointId) {
|
|
146
|
+
const failoverManager = this.failoverManagers.get(serviceId);
|
|
147
|
+
if (!failoverManager) {
|
|
148
|
+
throw new Error(`No failover manager found for service: ${serviceId}`);
|
|
149
|
+
}
|
|
150
|
+
return await failoverManager.manualFailover(targetEndpointId);
|
|
151
|
+
}
|
|
152
|
+
async manualFailback(serviceId) {
|
|
153
|
+
const failoverManager = this.failoverManagers.get(serviceId);
|
|
154
|
+
if (!failoverManager) {
|
|
155
|
+
throw new Error(`No failover manager found for service: ${serviceId}`);
|
|
156
|
+
}
|
|
157
|
+
return await failoverManager.manualFailback();
|
|
158
|
+
}
|
|
159
|
+
async getHealthStatus() {
|
|
160
|
+
const statuses = [];
|
|
161
|
+
for (const [serviceId, failoverManager] of this.failoverManagers){
|
|
162
|
+
const status = await failoverManager.getHealthStatus();
|
|
163
|
+
statuses.push({
|
|
164
|
+
service: serviceId,
|
|
165
|
+
status
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return statuses;
|
|
169
|
+
}
|
|
170
|
+
constructor(logger, config){
|
|
171
|
+
super(), _define_property(this, "redis", void 0), _define_property(this, "logger", void 0), _define_property(this, "config", void 0), _define_property(this, "isRunning", false), _define_property(this, "circuitBreakers", new Map()), _define_property(this, "failoverManagers", new Map()), _define_property(this, "healthMonitor", void 0), _define_property(this, "disasterRecovery", void 0), _define_property(this, "bulkheadManager", void 0), _define_property(this, "rateLimiter", void 0);
|
|
172
|
+
this.logger = logger;
|
|
173
|
+
this.config = config;
|
|
174
|
+
this.redis = createClient(config.redis);
|
|
175
|
+
this.healthMonitor = new HealthMonitor(logger, config);
|
|
176
|
+
this.disasterRecovery = new DisasterRecoveryManager(logger, config.disasterRecovery);
|
|
177
|
+
this.bulkheadManager = new BulkheadManager(config.bulkheads);
|
|
178
|
+
this.rateLimiter = new RateLimiter(config.rateLimiting);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
let CircuitBreaker = class CircuitBreaker extends EventEmitter {
|
|
182
|
+
async execute(operation, timeoutMs) {
|
|
183
|
+
const startTime = Date.now();
|
|
184
|
+
try {
|
|
185
|
+
if (this.state === "open") {
|
|
186
|
+
if (this.shouldAttemptReset()) {
|
|
187
|
+
this.setState("half_open");
|
|
188
|
+
this.halfOpenCalls = 0;
|
|
189
|
+
} else {
|
|
190
|
+
throw new Error(`Circuit breaker is OPEN for ${this.config.name}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (this.state === "half_open" && this.halfOpenCalls >= this.config.halfOpenMaxCalls) {
|
|
194
|
+
throw new Error(`Circuit breaker is HALF_OPEN and has exceeded max calls for ${this.config.name}`);
|
|
195
|
+
}
|
|
196
|
+
if (this.state === "half_open") {
|
|
197
|
+
this.halfOpenCalls++;
|
|
198
|
+
}
|
|
199
|
+
this.totalCalls++;
|
|
200
|
+
const result = await this.executeWithTimeout(operation, timeoutMs);
|
|
201
|
+
const responseTime = Date.now() - startTime;
|
|
202
|
+
this.recordSuccess(responseTime);
|
|
203
|
+
return result;
|
|
204
|
+
} catch (error) {
|
|
205
|
+
this.recordFailure();
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async executeWithTimeout(operation, timeoutMs) {
|
|
210
|
+
const timeout = timeoutMs || 30000;
|
|
211
|
+
return new Promise((resolve, reject)=>{
|
|
212
|
+
const timer = setTimeout(()=>{
|
|
213
|
+
this.recordTimeout();
|
|
214
|
+
reject(new Error(`Operation timed out after ${timeout}ms`));
|
|
215
|
+
}, timeout);
|
|
216
|
+
operation().then((result)=>{
|
|
217
|
+
clearTimeout(timer);
|
|
218
|
+
resolve(result);
|
|
219
|
+
}).catch((error)=>{
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
reject(error);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
recordSuccess(responseTime) {
|
|
226
|
+
this.successes++;
|
|
227
|
+
this.lastSuccessTime = new Date();
|
|
228
|
+
this.responseTimes.push(responseTime);
|
|
229
|
+
// Keep only last 100 response times
|
|
230
|
+
if (this.responseTimes.length > 100) {
|
|
231
|
+
this.responseTimes = this.responseTimes.slice(-100);
|
|
232
|
+
}
|
|
233
|
+
if (this.state === "half_open") {
|
|
234
|
+
this.setState("closed");
|
|
235
|
+
this.failures = 0;
|
|
236
|
+
}
|
|
237
|
+
this.logger.debug('Circuit breaker success', {
|
|
238
|
+
name: this.config.name,
|
|
239
|
+
state: this.state,
|
|
240
|
+
successes: this.successes,
|
|
241
|
+
failures: this.failures
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
recordFailure() {
|
|
245
|
+
this.failures++;
|
|
246
|
+
this.lastFailureTime = new Date();
|
|
247
|
+
if (this.state === "half_open") {
|
|
248
|
+
this.setState("open");
|
|
249
|
+
} else if (this.shouldOpenCircuit()) {
|
|
250
|
+
this.setState("open");
|
|
251
|
+
}
|
|
252
|
+
this.logger.debug('Circuit breaker failure', {
|
|
253
|
+
name: this.config.name,
|
|
254
|
+
state: this.state,
|
|
255
|
+
failures: this.failures,
|
|
256
|
+
threshold: this.config.failureThreshold
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
recordTimeout() {
|
|
260
|
+
this.timeouts++;
|
|
261
|
+
this.lastFailureTime = new Date();
|
|
262
|
+
this.recordFailure();
|
|
263
|
+
}
|
|
264
|
+
shouldOpenCircuit() {
|
|
265
|
+
return this.failures >= this.config.failureThreshold;
|
|
266
|
+
}
|
|
267
|
+
shouldAttemptReset() {
|
|
268
|
+
return Date.now() - this.stateChangedAt.getTime() >= this.config.recoveryTimeout;
|
|
269
|
+
}
|
|
270
|
+
setState(newState) {
|
|
271
|
+
const oldState = this.state;
|
|
272
|
+
this.state = newState;
|
|
273
|
+
this.stateChangedAt = new Date();
|
|
274
|
+
this.logger.info('Circuit breaker state changed', {
|
|
275
|
+
name: this.config.name,
|
|
276
|
+
from: oldState,
|
|
277
|
+
to: newState
|
|
278
|
+
});
|
|
279
|
+
this.emit('stateChange', newState);
|
|
280
|
+
if (this.config.stateChangeHandler) {
|
|
281
|
+
this.config.stateChangeHandler(newState);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
getMetrics() {
|
|
285
|
+
return {
|
|
286
|
+
state: this.state,
|
|
287
|
+
failures: this.failures,
|
|
288
|
+
successes: this.successes,
|
|
289
|
+
timeouts: this.timeouts,
|
|
290
|
+
totalCalls: this.totalCalls,
|
|
291
|
+
failureRate: this.totalCalls > 0 ? this.failures / this.totalCalls : 0,
|
|
292
|
+
lastFailureTime: this.lastFailureTime,
|
|
293
|
+
lastSuccessTime: this.lastSuccessTime,
|
|
294
|
+
stateChangedAt: this.stateChangedAt,
|
|
295
|
+
averageResponseTime: this.responseTimes.length > 0 ? this.responseTimes.reduce((sum, time)=>sum + time, 0) / this.responseTimes.length : 0
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
destroy() {
|
|
299
|
+
this.removeAllListeners();
|
|
300
|
+
}
|
|
301
|
+
constructor(config, logger){
|
|
302
|
+
super(), _define_property(this, "config", void 0), _define_property(this, "logger", void 0), _define_property(this, "state", "closed"), _define_property(this, "failures", 0), _define_property(this, "successes", 0), _define_property(this, "timeouts", 0), _define_property(this, "totalCalls", 0), _define_property(this, "lastFailureTime", void 0), _define_property(this, "lastSuccessTime", void 0), _define_property(this, "stateChangedAt", new Date()), _define_property(this, "halfOpenCalls", 0), _define_property(this, "responseTimes", []);
|
|
303
|
+
this.config = config;
|
|
304
|
+
this.logger = logger;
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
let FailoverManager = class FailoverManager extends EventEmitter {
|
|
308
|
+
async start() {
|
|
309
|
+
this.startHealthChecks();
|
|
310
|
+
this.logger.info('Failover manager started', {
|
|
311
|
+
primary: this.config.primary.id,
|
|
312
|
+
secondaryCount: this.config.secondary.length
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
async stop() {
|
|
316
|
+
if (this.healthCheckTimer) {
|
|
317
|
+
clearInterval(this.healthCheckTimer);
|
|
318
|
+
}
|
|
319
|
+
this.logger.info('Failover manager stopped');
|
|
320
|
+
}
|
|
321
|
+
async execute(operation, options = {}) {
|
|
322
|
+
const endpoint = this.state.active;
|
|
323
|
+
try {
|
|
324
|
+
const result = await operation();
|
|
325
|
+
this.recordSuccess(endpoint);
|
|
326
|
+
return result;
|
|
327
|
+
} catch (error) {
|
|
328
|
+
this.recordFailure(endpoint, error);
|
|
329
|
+
if (this.shouldFailover()) {
|
|
330
|
+
await this.performFailover();
|
|
331
|
+
// Retry with new endpoint
|
|
332
|
+
return await operation();
|
|
333
|
+
}
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async manualFailover(targetEndpointId) {
|
|
338
|
+
let targetEndpoint;
|
|
339
|
+
if (targetEndpointId) {
|
|
340
|
+
targetEndpoint = this.config.secondary.find((ep)=>ep.id === targetEndpointId) || this.config.secondary.find((ep)=>ep.id === targetEndpointId);
|
|
341
|
+
if (!targetEndpoint) {
|
|
342
|
+
throw new Error(`Secondary endpoint not found: ${targetEndpointId}`);
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
targetEndpoint = this.selectBestSecondary();
|
|
346
|
+
}
|
|
347
|
+
await this.performFailoverTo(targetEndpoint);
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
async manualFailback() {
|
|
351
|
+
if (!this.state.inFailover) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
const primaryHealthy = this.healthStatuses.get(this.config.primary.id)?.healthy ?? false;
|
|
355
|
+
if (!primaryHealthy) {
|
|
356
|
+
this.logger.warn('Cannot failback to unhealthy primary', {
|
|
357
|
+
primaryId: this.config.primary.id
|
|
358
|
+
});
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
await this.performFailback();
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
startHealthChecks() {
|
|
365
|
+
this.healthCheckTimer = setInterval(async ()=>{
|
|
366
|
+
await this.performHealthChecks();
|
|
367
|
+
}, this.config.healthCheckInterval);
|
|
368
|
+
// Initial health check
|
|
369
|
+
this.performHealthChecks();
|
|
370
|
+
}
|
|
371
|
+
async performHealthChecks() {
|
|
372
|
+
const endpoints = [
|
|
373
|
+
this.config.primary,
|
|
374
|
+
...this.config.secondary
|
|
375
|
+
];
|
|
376
|
+
for (const endpoint of endpoints){
|
|
377
|
+
try {
|
|
378
|
+
const startTime = Date.now();
|
|
379
|
+
const healthy = await this.checkEndpointHealth(endpoint);
|
|
380
|
+
const responseTime = Date.now() - startTime;
|
|
381
|
+
this.updateHealthStatus(endpoint, healthy, responseTime);
|
|
382
|
+
} catch (error) {
|
|
383
|
+
this.updateHealthStatus(endpoint, false, 0, error instanceof Error ? error.message : String(error));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
await this.evaluateFailoverConditions();
|
|
387
|
+
await this.evaluateFailbackConditions();
|
|
388
|
+
}
|
|
389
|
+
async checkEndpointHealth(endpoint) {
|
|
390
|
+
// Implementation would perform actual health check
|
|
391
|
+
// For now, simulate with random success
|
|
392
|
+
return Math.random() > 0.1; // 90% success rate
|
|
393
|
+
}
|
|
394
|
+
updateHealthStatus(endpoint, healthy, responseTime, error) {
|
|
395
|
+
const current = this.healthStatuses.get(endpoint.id) || {
|
|
396
|
+
endpoint,
|
|
397
|
+
healthy: true,
|
|
398
|
+
responseTime: 0,
|
|
399
|
+
lastCheck: new Date(),
|
|
400
|
+
consecutiveFailures: 0,
|
|
401
|
+
consecutiveSuccesses: 0
|
|
402
|
+
};
|
|
403
|
+
if (healthy) {
|
|
404
|
+
current.consecutiveSuccesses++;
|
|
405
|
+
current.consecutiveFailures = 0;
|
|
406
|
+
} else {
|
|
407
|
+
current.consecutiveFailures++;
|
|
408
|
+
current.consecutiveSuccesses = 0;
|
|
409
|
+
}
|
|
410
|
+
current.healthy = healthy;
|
|
411
|
+
current.responseTime = responseTime;
|
|
412
|
+
current.lastCheck = new Date();
|
|
413
|
+
current.error = error;
|
|
414
|
+
this.healthStatuses.set(endpoint.id, current);
|
|
415
|
+
}
|
|
416
|
+
async evaluateFailoverConditions() {
|
|
417
|
+
if (this.state.inFailover) {
|
|
418
|
+
return; // Already in failover mode
|
|
419
|
+
}
|
|
420
|
+
const primaryStatus = this.healthStatuses.get(this.config.primary.id);
|
|
421
|
+
if (!primaryStatus || primaryStatus.healthy) {
|
|
422
|
+
return; // Primary is healthy
|
|
423
|
+
}
|
|
424
|
+
const consecutiveFailures = primaryStatus.consecutiveFailures;
|
|
425
|
+
if (consecutiveFailures >= this.config.failoverThreshold) {
|
|
426
|
+
await this.performFailover();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async evaluateFailbackConditions() {
|
|
430
|
+
if (!this.state.inFailover || !this.config.automaticFailback) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const primaryStatus = this.healthStatuses.get(this.config.primary.id);
|
|
434
|
+
if (!primaryStatus || !primaryStatus.healthy) {
|
|
435
|
+
return; // Primary is not healthy
|
|
436
|
+
}
|
|
437
|
+
const consecutiveSuccesses = primaryStatus.consecutiveSuccesses;
|
|
438
|
+
if (consecutiveSuccesses >= this.config.failbackThreshold) {
|
|
439
|
+
await this.performFailback();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
shouldFailover() {
|
|
443
|
+
const activeStatus = this.healthStatuses.get(this.state.active.id);
|
|
444
|
+
return activeStatus ? !activeStatus.healthy : false;
|
|
445
|
+
}
|
|
446
|
+
async performFailover() {
|
|
447
|
+
const targetEndpoint = this.selectBestSecondary();
|
|
448
|
+
await this.performFailoverTo(targetEndpoint);
|
|
449
|
+
}
|
|
450
|
+
async performFailoverTo(targetEndpoint) {
|
|
451
|
+
const previousActive = this.state.active;
|
|
452
|
+
this.state.active = targetEndpoint;
|
|
453
|
+
this.state.inFailover = true;
|
|
454
|
+
this.state.failoverCount++;
|
|
455
|
+
this.state.lastFailover = new Date();
|
|
456
|
+
this.logger.warn('Failover performed', {
|
|
457
|
+
from: previousActive.id,
|
|
458
|
+
to: targetEndpoint.id,
|
|
459
|
+
failoverCount: this.state.failoverCount
|
|
460
|
+
});
|
|
461
|
+
this.emit('failover', {
|
|
462
|
+
previous: previousActive,
|
|
463
|
+
current: targetEndpoint,
|
|
464
|
+
state: this.state
|
|
465
|
+
});
|
|
466
|
+
// Store failover state in Redis
|
|
467
|
+
await this.redis.setEx(`swarm:error-recovery-final:failover:${this.config.primary.id}`, 3600, JSON.stringify(this.state));
|
|
468
|
+
}
|
|
469
|
+
async performFailback() {
|
|
470
|
+
const previousActive = this.state.active;
|
|
471
|
+
this.state.active = this.config.primary;
|
|
472
|
+
this.state.inFailover = false;
|
|
473
|
+
this.state.lastFailback = new Date();
|
|
474
|
+
this.logger.info('Failback performed', {
|
|
475
|
+
from: previousActive.id,
|
|
476
|
+
to: this.config.primary.id,
|
|
477
|
+
duration: Date.now() - this.state.lastFailover.getTime()
|
|
478
|
+
});
|
|
479
|
+
this.emit('failback', {
|
|
480
|
+
previous: previousActive,
|
|
481
|
+
current: this.config.primary,
|
|
482
|
+
state: this.state
|
|
483
|
+
});
|
|
484
|
+
// Clear failover state from Redis
|
|
485
|
+
await this.redis.del(`swarm:error-recovery-final:failover:${this.config.primary.id}`);
|
|
486
|
+
}
|
|
487
|
+
selectBestSecondary() {
|
|
488
|
+
const healthySecondaries = this.config.secondary.filter((ep)=>{
|
|
489
|
+
const status = this.healthStatuses.get(ep.id);
|
|
490
|
+
return status && status.healthy;
|
|
491
|
+
});
|
|
492
|
+
if (healthySecondaries.length === 0) {
|
|
493
|
+
// No healthy secondaries, select by priority
|
|
494
|
+
return this.config.secondary.reduce((best, current)=>current.priority < best.priority ? current : best);
|
|
495
|
+
}
|
|
496
|
+
// Select healthy secondary with best response time
|
|
497
|
+
return healthySecondaries.reduce((best, current)=>{
|
|
498
|
+
const bestStatus = this.healthStatuses.get(best.id);
|
|
499
|
+
const currentStatus = this.healthStatuses.get(current.id);
|
|
500
|
+
return currentStatus.responseTime < bestStatus.responseTime ? current : best;
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
recordSuccess(endpoint) {
|
|
504
|
+
const status = this.healthStatuses.get(endpoint.id);
|
|
505
|
+
if (status) {
|
|
506
|
+
status.consecutiveSuccesses++;
|
|
507
|
+
status.consecutiveFailures = 0;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
recordFailure(endpoint, error) {
|
|
511
|
+
const status = this.healthStatuses.get(endpoint.id);
|
|
512
|
+
if (status) {
|
|
513
|
+
status.consecutiveFailures++;
|
|
514
|
+
status.consecutiveSuccesses = 0;
|
|
515
|
+
status.error = error instanceof Error ? error.message : String(error);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
getState() {
|
|
519
|
+
return {
|
|
520
|
+
...this.state
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
async getHealthStatus() {
|
|
524
|
+
return this.healthStatuses.get(this.state.active.id) || {
|
|
525
|
+
endpoint: this.state.active,
|
|
526
|
+
healthy: false,
|
|
527
|
+
responseTime: 0,
|
|
528
|
+
lastCheck: new Date(),
|
|
529
|
+
consecutiveFailures: 0,
|
|
530
|
+
consecutiveSuccesses: 0,
|
|
531
|
+
error: 'No health status available'
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
constructor(config, logger, redis){
|
|
535
|
+
super(), _define_property(this, "config", void 0), _define_property(this, "logger", void 0), _define_property(this, "redis", void 0), _define_property(this, "state", void 0), _define_property(this, "healthStatuses", new Map()), _define_property(this, "healthCheckTimer", void 0);
|
|
536
|
+
this.config = config;
|
|
537
|
+
this.logger = logger;
|
|
538
|
+
this.redis = redis;
|
|
539
|
+
this.state = {
|
|
540
|
+
primary: config.primary,
|
|
541
|
+
active: config.primary,
|
|
542
|
+
secondary: [
|
|
543
|
+
...config.secondary
|
|
544
|
+
],
|
|
545
|
+
failoverCount: 0,
|
|
546
|
+
lastFailover: new Date(),
|
|
547
|
+
inFailover: false,
|
|
548
|
+
automaticFailbackEnabled: config.automaticFailback
|
|
549
|
+
};
|
|
550
|
+
// Initialize health statuses
|
|
551
|
+
this.updateHealthStatus(config.primary, true, 0);
|
|
552
|
+
config.secondary.forEach((endpoint)=>{
|
|
553
|
+
this.updateHealthStatus(endpoint, true, 0);
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
let HealthMonitor = class HealthMonitor {
|
|
558
|
+
async start() {
|
|
559
|
+
this.isRunning = true;
|
|
560
|
+
this.logger.info('Health monitor started');
|
|
561
|
+
}
|
|
562
|
+
async stop() {
|
|
563
|
+
this.isRunning = false;
|
|
564
|
+
this.logger.info('Health monitor stopped');
|
|
565
|
+
}
|
|
566
|
+
constructor(logger, config){
|
|
567
|
+
_define_property(this, "logger", void 0);
|
|
568
|
+
_define_property(this, "config", void 0);
|
|
569
|
+
_define_property(this, "isRunning", false);
|
|
570
|
+
this.logger = logger;
|
|
571
|
+
this.config = config;
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
let DisasterRecoveryManager = class DisasterRecoveryManager {
|
|
575
|
+
async start() {
|
|
576
|
+
if (!this.config.enabled) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
this.isRunning = true;
|
|
580
|
+
this.logger.info('Disaster recovery manager started');
|
|
581
|
+
}
|
|
582
|
+
async stop() {
|
|
583
|
+
this.isRunning = false;
|
|
584
|
+
this.logger.info('Disaster recovery manager stopped');
|
|
585
|
+
}
|
|
586
|
+
async executeProcedure(procedureId, context = {}) {
|
|
587
|
+
const procedure = this.config.emergencyProcedures.find((p)=>p.id === procedureId);
|
|
588
|
+
if (!procedure) {
|
|
589
|
+
throw new Error(`Emergency procedure not found: ${procedureId}`);
|
|
590
|
+
}
|
|
591
|
+
this.logger.warn('Executing emergency procedure', {
|
|
592
|
+
id: procedureId,
|
|
593
|
+
name: procedure.name,
|
|
594
|
+
severity: procedure.severity
|
|
595
|
+
});
|
|
596
|
+
try {
|
|
597
|
+
for (const step of procedure.steps){
|
|
598
|
+
await this.executeStep(step, context);
|
|
599
|
+
}
|
|
600
|
+
this.logger.info('Emergency procedure completed successfully', {
|
|
601
|
+
id: procedureId
|
|
602
|
+
});
|
|
603
|
+
return true;
|
|
604
|
+
} catch (error) {
|
|
605
|
+
this.logger.error('Emergency procedure failed', {
|
|
606
|
+
id: procedureId,
|
|
607
|
+
error: error instanceof Error ? error.message : String(error)
|
|
608
|
+
});
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
async executeStep(step, context) {
|
|
613
|
+
this.logger.debug('Executing emergency step', {
|
|
614
|
+
id: step.id,
|
|
615
|
+
name: step.name,
|
|
616
|
+
action: step.action
|
|
617
|
+
});
|
|
618
|
+
// Implementation would execute the actual step
|
|
619
|
+
// For now, simulate execution
|
|
620
|
+
await new Promise((resolve)=>setTimeout(resolve, 1000));
|
|
621
|
+
}
|
|
622
|
+
constructor(logger, config){
|
|
623
|
+
_define_property(this, "logger", void 0);
|
|
624
|
+
_define_property(this, "config", void 0);
|
|
625
|
+
_define_property(this, "isRunning", false);
|
|
626
|
+
this.logger = logger;
|
|
627
|
+
this.config = config;
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
let BulkheadManager = class BulkheadManager {
|
|
631
|
+
async execute(operation) {
|
|
632
|
+
if (!this.config.enabled) {
|
|
633
|
+
return await operation();
|
|
634
|
+
}
|
|
635
|
+
return new Promise((resolve, reject)=>{
|
|
636
|
+
if (this.runningCalls < this.config.maxConcurrentCalls) {
|
|
637
|
+
this.executeNow(operation, resolve, reject);
|
|
638
|
+
} else if (this.queue.length < this.config.maxQueueSize) {
|
|
639
|
+
this.queue.push({
|
|
640
|
+
resolve,
|
|
641
|
+
reject,
|
|
642
|
+
operation
|
|
643
|
+
});
|
|
644
|
+
} else {
|
|
645
|
+
reject(new Error('Bulkhead queue is full'));
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
async executeNow(operation, resolve, reject) {
|
|
650
|
+
this.runningCalls++;
|
|
651
|
+
const timeout = setTimeout(()=>{
|
|
652
|
+
this.runningCalls--;
|
|
653
|
+
reject(new Error('Bulkhead operation timed out'));
|
|
654
|
+
this.processQueue();
|
|
655
|
+
}, this.config.timeout);
|
|
656
|
+
try {
|
|
657
|
+
const result = await operation();
|
|
658
|
+
clearTimeout(timeout);
|
|
659
|
+
this.runningCalls--;
|
|
660
|
+
resolve(result);
|
|
661
|
+
this.processQueue();
|
|
662
|
+
} catch (error) {
|
|
663
|
+
clearTimeout(timeout);
|
|
664
|
+
this.runningCalls--;
|
|
665
|
+
reject(error);
|
|
666
|
+
this.processQueue();
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
processQueue() {
|
|
670
|
+
if (this.queue.length === 0 || this.runningCalls >= this.config.maxConcurrentCalls) {
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
const { resolve, reject, operation } = this.queue.shift();
|
|
674
|
+
this.executeNow(operation, resolve, reject);
|
|
675
|
+
}
|
|
676
|
+
constructor(config){
|
|
677
|
+
_define_property(this, "config", void 0);
|
|
678
|
+
_define_property(this, "runningCalls", 0);
|
|
679
|
+
_define_property(this, "queue", []);
|
|
680
|
+
this.config = config;
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
let RateLimiter = class RateLimiter {
|
|
684
|
+
async acquire() {
|
|
685
|
+
if (!this.config.enabled) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
this.refillTokens();
|
|
689
|
+
if (this.tokens >= 1) {
|
|
690
|
+
this.tokens--;
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
// Wait for token refill
|
|
694
|
+
const waitTime = Math.ceil(1000 / this.config.requestsPerSecond);
|
|
695
|
+
await new Promise((resolve)=>setTimeout(resolve, waitTime));
|
|
696
|
+
await this.acquire();
|
|
697
|
+
}
|
|
698
|
+
refillTokens() {
|
|
699
|
+
const now = Date.now();
|
|
700
|
+
const timePassed = now - this.lastRefill;
|
|
701
|
+
const tokensToAdd = Math.floor(timePassed * this.config.requestsPerSecond / 1000);
|
|
702
|
+
if (tokensToAdd > 0) {
|
|
703
|
+
this.tokens = Math.min(this.tokens + tokensToAdd, this.config.burstSize);
|
|
704
|
+
this.lastRefill = now;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
constructor(config){
|
|
708
|
+
_define_property(this, "config", void 0);
|
|
709
|
+
_define_property(this, "tokens", 0);
|
|
710
|
+
_define_property(this, "lastRefill", Date.now());
|
|
711
|
+
this.config = config;
|
|
712
|
+
this.tokens = config.requestsPerSecond;
|
|
713
|
+
}
|
|
714
|
+
};
|