UNPKG

claude-flow-novice

Version:

Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture Includes CodeSearch (hybrid SQLite + pgvector), mem0/memgraph specialists, and all CFN skills.

234 lines (233 loc) 8.62 kB
/** * Error Aggregation System * * Provides error aggregation, correlation tracking, and circuit breaker patterns * for multi-database operations. * * Features: * - Aggregates errors from multiple database systems * - Tracks error correlation across operations * - Implements circuit breaker for repeated failures * - Provides error analysis and reporting * * Part of: Critical Error Handling Fixes (Architecture Review) */ import { DatabaseErrorCode } from './database-service/types.js'; import { createLogger } from './logging.js'; import { v4 as uuidv4 } from 'uuid'; import { CircuitBreakerState, CircuitBreakerConfig, CircuitBreakerRegistry } from './circuit-breaker.js'; // Re-export circuit breaker types for backward compatibility export { CircuitBreakerState, CircuitBreakerConfig }; /** * Error severity levels */ export var ErrorSeverity = /*#__PURE__*/ function(ErrorSeverity) { ErrorSeverity["LOW"] = "low"; ErrorSeverity["MEDIUM"] = "medium"; ErrorSeverity["HIGH"] = "high"; ErrorSeverity["CRITICAL"] = "critical"; return ErrorSeverity; }({}); // Circuit breaker types now imported from ./circuit-breaker module /** * Error aggregator class */ export class ErrorAggregator { logger; errors = []; correlationId; circuitBreakerConfig; constructor(correlationId, circuitBreakerConfig){ this.correlationId = correlationId || uuidv4(); this.logger = createLogger('error-aggregator'); // Store circuit breaker configuration for registry this.circuitBreakerConfig = { failureThreshold: circuitBreakerConfig?.failureThreshold ?? 5, successThreshold: circuitBreakerConfig?.successThreshold ?? 2, timeout: circuitBreakerConfig?.timeout ?? 60000, windowSize: circuitBreakerConfig?.windowSize ?? 120000 }; } /** * Add error to aggregation */ addError(system, error, operationContext) { const aggregatedError = { correlationId: uuidv4(), timestamp: new Date(), system, error, severity: this.determineSeverity(error), operationContext, stackTrace: error.originalError?.stack }; this.errors.push(aggregatedError); // Update circuit breaker this.recordFailure(system); // Log error with correlation ID this.logger.error('Database operation failed', error.originalError, { correlationId: this.correlationId, errorCorrelationId: aggregatedError.correlationId, system, errorCode: error.code, message: error.message, severity: aggregatedError.severity }); return aggregatedError; } /** * Record successful operation (for circuit breaker) */ recordSuccess(system) { // Use circuit breaker registry - success is tracked automatically via execute() // This method is kept for backward compatibility but delegates to registry const breaker = CircuitBreakerRegistry.getOrCreate(system, this.circuitBreakerConfig); // Success tracking is handled internally by CircuitBreaker.execute() // This is just a manual success recording for compatibility this.logger.debug('Manual success recorded', { system, correlationId: this.correlationId }); } /** * Record failed operation (for circuit breaker) */ recordFailure(system) { // Failure tracking is handled by the circuit breaker registry // This is called when addError is invoked const breaker = CircuitBreakerRegistry.getOrCreate(system, this.circuitBreakerConfig); this.logger.debug('Failure recorded via error aggregation', { system, state: breaker.getState(), correlationId: this.correlationId }); } /** * Check if circuit breaker allows operation */ isCircuitOpen(system) { const breaker = CircuitBreakerRegistry.get(system); return breaker ? !breaker.isHealthy() : false; } /** * Get aggregation result */ getResult(expectedSystems) { const errorsBySystem = {}; const errorsBySeverity = { ["low"]: [], ["medium"]: [], ["high"]: [], ["critical"]: [] }; // Group errors for (const error of this.errors){ // By system if (!errorsBySystem[error.system]) { errorsBySystem[error.system] = []; } errorsBySystem[error.system].push(error); // By severity errorsBySeverity[error.severity].push(error); } // Check if all systems failed const failedSystems = Object.keys(errorsBySystem); const allSystemsFailed = expectedSystems.every((system)=>failedSystems.includes(system)); // Check for critical errors const hasCriticalErrors = errorsBySeverity["critical"].length > 0; return { totalErrors: this.errors.length, errorsBySystem, errorsBySeverity, allErrors: [ ...this.errors ], correlationId: this.correlationId, allSystemsFailed, hasCriticalErrors }; } /** * Determine error severity */ determineSeverity(error) { switch(error.code){ case DatabaseErrorCode.CONNECTION_FAILED: case DatabaseErrorCode.TRANSACTION_FAILED: return "critical"; case DatabaseErrorCode.QUERY_FAILED: case DatabaseErrorCode.TIMEOUT: return "high"; case DatabaseErrorCode.VALIDATION_FAILED: case DatabaseErrorCode.CONSTRAINT_VIOLATION: return "medium"; case DatabaseErrorCode.NOT_FOUND: case DatabaseErrorCode.DUPLICATE_KEY: return "low"; default: return "medium"; } } /** * Check if errors should cause operation failure */ shouldFailOperation(expectedSystems) { const result = this.getResult(expectedSystems); // Fail if all systems failed if (result.allSystemsFailed) { return true; } // Fail if any critical errors if (result.hasCriticalErrors) { return true; } return false; } /** * Create error report */ createReport() { const result = this.getResult([]); const lines = [ '=== Error Aggregation Report ===', `Correlation ID: ${this.correlationId}`, `Total Errors: ${result.totalErrors}`, `All Systems Failed: ${result.allSystemsFailed}`, `Critical Errors: ${result.hasCriticalErrors}`, '', '--- Errors by System ---' ]; for (const [system, errors] of Object.entries(result.errorsBySystem)){ lines.push(`${system}: ${errors.length} error(s)`); for (const error of errors){ lines.push(` - [${error.severity}] ${error.error.message}`); } } lines.push(''); lines.push('--- Errors by Severity ---'); for (const [severity, errors] of Object.entries(result.errorsBySeverity)){ if (errors.length > 0) { lines.push(`${severity}: ${errors.length} error(s)`); } } lines.push(''); lines.push('--- Circuit Breaker Status ---'); const allMetrics = CircuitBreakerRegistry.getAllMetrics(); for (const [system, metrics] of Object.entries(allMetrics)){ lines.push(`${system}: ${metrics.state} (failures: ${metrics.failures}, successes: ${metrics.successes})`); } return lines.join('\n'); } /** * Get correlation ID */ getCorrelationId() { return this.correlationId; } /** * Reset aggregator (for reuse) */ reset() { this.errors = []; this.correlationId = uuidv4(); } /** * Get circuit breaker state for system */ getCircuitBreakerState(system) { const breaker = CircuitBreakerRegistry.get(system); return breaker?.getState() || CircuitBreakerState.CLOSED; } } /** * Create error aggregator */ export function createErrorAggregator(correlationId, circuitBreakerConfig) { return new ErrorAggregator(correlationId, circuitBreakerConfig); } //# sourceMappingURL=error-aggregator.js.map