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
JavaScript
/**
* 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