UNPKG

rezilient.js

Version:

Rezilient.js - Revolutionary offline-first framework with AI-awareness, principle-driven development, carbon-conscious computing, and self-healing capabilities

737 lines (618 loc) 20.4 kB
/** * Aether.js Revolutionary Error Boundary System * * Features: * - Predictive error prevention * - Self-healing capabilities * - Context-aware error recovery * - User experience preservation * - Learning from failures * - Graceful degradation strategies */ import { withPrinciples } from './AetherPrinciples.js'; /** * Error Severity Levels */ export const ERROR_SEVERITY = { TRACE: 0, // Debug information INFO: 1, // Informational WARNING: 2, // Warning conditions ERROR: 3, // Error conditions CRITICAL: 4, // Critical conditions FATAL: 5 // System unusable }; /** * Recovery Strategies */ export const RECOVERY_STRATEGIES = { RETRY: 'retry', FALLBACK: 'fallback', GRACEFUL_DEGRADATION: 'graceful_degradation', USER_INTERVENTION: 'user_intervention', SYSTEM_RESTART: 'system_restart', SAFE_MODE: 'safe_mode' }; /** * Revolutionary Error Boundary */ export class AetherErrorBoundary { constructor(options = {}) { this.options = { maxRetries: 3, retryDelay: 1000, enablePrediction: true, enableSelfHealing: true, enableLearning: true, fallbackComponent: null, onError: null, ...options }; // Error tracking this.errorHistory = []; this.errorPatterns = new Map(); this.recoveryAttempts = new Map(); this.healingStrategies = new Map(); // Predictive system this.errorPredictors = new Map(); this.riskFactors = new Map(); // Performance monitoring this.performanceMetrics = { errorRate: 0, recoveryRate: 0, meanTimeToRecovery: 0, userImpact: 0 }; this.initializeErrorBoundary(); } /** * Initialize error boundary system */ initializeErrorBoundary() { this.setupGlobalErrorHandling(); this.setupPredictiveSystem(); this.setupSelfHealingSystem(); this.setupPerformanceMonitoring(); } /** * Global error handling setup */ setupGlobalErrorHandling() { // Catch unhandled promise rejections if (typeof window !== 'undefined') { window.addEventListener('unhandledrejection', (event) => { this.handleError(event.reason, { type: 'unhandled_promise_rejection', source: 'global' }); }); // Catch global errors window.addEventListener('error', (event) => { this.handleError(event.error, { type: 'global_error', source: event.filename, line: event.lineno, column: event.colno }); }); } } /** * Predictive error system */ setupPredictiveSystem() { if (!this.options.enablePrediction) return; this.errorPredictor = { analyzeRiskFactors: (context) => { const riskScore = this.calculateRiskScore(context); if (riskScore > 0.7) { this.preventiveAction(context, riskScore); } return riskScore; }, predictErrorProbability: (operation, context) => { const historicalData = this.getHistoricalErrorData(operation); const contextualRisk = this.assessContextualRisk(context); return this.combineRiskFactors(historicalData, contextualRisk); }, recommendPreventiveMeasures: (riskScore, context) => { const measures = []; if (riskScore > 0.8) { measures.push({ type: 'circuit_breaker', description: 'Temporarily disable risky operations', priority: 'high' }); } if (riskScore > 0.6) { measures.push({ type: 'resource_allocation', description: 'Allocate additional resources', priority: 'medium' }); } if (riskScore > 0.4) { measures.push({ type: 'monitoring_increase', description: 'Increase monitoring frequency', priority: 'low' }); } return measures; } }; } /** * Self-healing system */ setupSelfHealingSystem() { if (!this.options.enableSelfHealing) return; this.selfHealer = { diagnose: (error, context) => { const diagnosis = { errorType: this.classifyError(error), severity: this.assessSeverity(error, context), rootCause: this.identifyRootCause(error, context), affectedSystems: this.identifyAffectedSystems(error, context), healingStrategy: null }; diagnosis.healingStrategy = this.selectHealingStrategy(diagnosis); return diagnosis; }, heal: async (diagnosis) => { const strategy = diagnosis.healingStrategy; try { const result = await this.executeHealingStrategy(strategy, diagnosis); if (result.success) { this.recordSuccessfulHealing(diagnosis, strategy, result); } else { this.escalateHealing(diagnosis, result); } return result; } catch (healingError) { return { success: false, error: healingError, requiresEscalation: true }; } }, learn: (diagnosis, strategy, result) => { if (!this.options.enableLearning) return; const learningData = { errorPattern: this.extractErrorPattern(diagnosis), strategy: strategy.type, success: result.success, context: diagnosis.context, timestamp: Date.now() }; this.updateHealingKnowledge(learningData); } }; } /** * Performance monitoring */ setupPerformanceMonitoring() { this.performanceMonitor = { trackError: (error, context) => { this.performanceMetrics.errorRate = this.calculateErrorRate(); }, trackRecovery: (recovery) => { this.performanceMetrics.recoveryRate = this.calculateRecoveryRate(); this.performanceMetrics.meanTimeToRecovery = this.calculateMTTR(); }, trackUserImpact: (impact) => { this.performanceMetrics.userImpact = this.calculateUserImpact(impact); }, generateReport: () => { return { ...this.performanceMetrics, totalErrors: this.errorHistory.length, uniqueErrorTypes: new Set(this.errorHistory.map(e => e.type)).size, healingSuccessRate: this.calculateHealingSuccessRate(), timestamp: Date.now() }; } }; } /** * Main error handling method */ async handleError(error, context = {}) { const errorId = this.generateErrorId(); const timestamp = Date.now(); // Record error const errorRecord = { id: errorId, error, context, timestamp, severity: this.assessSeverity(error, context), handled: false, recovered: false }; this.errorHistory.push(errorRecord); this.updateErrorPatterns(errorRecord); // Attempt recovery try { const recovery = await this.attemptRecovery(errorRecord); errorRecord.recovered = recovery.success; errorRecord.recoveryStrategy = recovery.strategy; if (recovery.success) { this.performanceMonitor.trackRecovery(recovery); return recovery; } else { return this.handleRecoveryFailure(errorRecord, recovery); } } catch (recoveryError) { return this.handleCriticalFailure(errorRecord, recoveryError); } } /** * Attempt error recovery */ async attemptRecovery(errorRecord) { const { error, context } = errorRecord; // Check if we've seen this error before const knownPattern = this.findKnownErrorPattern(error); if (knownPattern && knownPattern.successfulStrategy) { return this.executeRecoveryStrategy(knownPattern.successfulStrategy, errorRecord); } // Try predictive healing if enabled if (this.options.enableSelfHealing) { const diagnosis = this.selfHealer.diagnose(error, context); const healingResult = await this.selfHealer.heal(diagnosis); if (healingResult.success) { this.selfHealer.learn(diagnosis, diagnosis.healingStrategy, healingResult); return { success: true, strategy: RECOVERY_STRATEGIES.FALLBACK, method: 'self_healing', result: healingResult }; } } // Try standard recovery strategies const strategies = this.getRecoveryStrategies(errorRecord); for (const strategy of strategies) { try { const result = await this.executeRecoveryStrategy(strategy, errorRecord); if (result.success) { this.recordSuccessfulStrategy(errorRecord, strategy); return result; } } catch (strategyError) { // Continue to next strategy continue; } } return { success: false, strategy: null, reason: 'All recovery strategies failed' }; } /** * Execute recovery strategy */ async executeRecoveryStrategy(strategy, errorRecord) { switch (strategy.type) { case RECOVERY_STRATEGIES.RETRY: return this.executeRetryStrategy(strategy, errorRecord); case RECOVERY_STRATEGIES.FALLBACK: return this.executeFallbackStrategy(strategy, errorRecord); case RECOVERY_STRATEGIES.GRACEFUL_DEGRADATION: return this.executeGracefulDegradation(strategy, errorRecord); case RECOVERY_STRATEGIES.USER_INTERVENTION: return this.requestUserIntervention(strategy, errorRecord); case RECOVERY_STRATEGIES.SAFE_MODE: return this.enterSafeMode(strategy, errorRecord); default: throw new Error(`Unknown recovery strategy: ${strategy.type}`); } } /** * Retry strategy */ async executeRetryStrategy(strategy, errorRecord) { const maxRetries = strategy.maxRetries || this.options.maxRetries; const delay = strategy.delay || this.options.retryDelay; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { await this.delay(delay * attempt); // Exponential backoff // Re-execute the failed operation const result = await this.retryOperation(errorRecord); return { success: true, strategy: RECOVERY_STRATEGIES.RETRY, attempts: attempt, result }; } catch (retryError) { if (attempt === maxRetries) { return { success: false, strategy: RECOVERY_STRATEGIES.RETRY, attempts: attempt, error: retryError }; } } } } /** * Fallback strategy */ async executeFallbackStrategy(strategy, errorRecord) { try { const fallbackComponent = strategy.fallback || this.options.fallbackComponent; if (!fallbackComponent) { return { success: false, strategy: RECOVERY_STRATEGIES.FALLBACK, reason: 'No fallback component available' }; } const result = await this.activateFallback(fallbackComponent, errorRecord); return { success: true, strategy: RECOVERY_STRATEGIES.FALLBACK, fallback: fallbackComponent, result }; } catch (fallbackError) { return { success: false, strategy: RECOVERY_STRATEGIES.FALLBACK, error: fallbackError }; } } /** * Graceful degradation */ async executeGracefulDegradation(strategy, errorRecord) { try { const degradedFeatures = this.identifyDegradableFeatures(errorRecord); const essentialFeatures = this.identifyEssentialFeatures(errorRecord); // Disable non-essential features await this.disableFeatures(degradedFeatures); // Ensure essential features remain functional await this.ensureEssentialFeatures(essentialFeatures); return { success: true, strategy: RECOVERY_STRATEGIES.GRACEFUL_DEGRADATION, degradedFeatures, essentialFeatures }; } catch (degradationError) { return { success: false, strategy: RECOVERY_STRATEGIES.GRACEFUL_DEGRADATION, error: degradationError }; } } /** * Get error boundary status */ getStatus() { return { errorHistory: this.errorHistory.slice(-10), // Last 10 errors errorPatterns: Array.from(this.errorPatterns.entries()), performanceMetrics: this.performanceMonitor.generateReport(), healingStrategies: Array.from(this.healingStrategies.entries()), options: this.options }; } // Helper methods (simplified implementations) generateErrorId() { return `err_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } assessSeverity(error, context) { // Simplified severity assessment if (error.name === 'TypeError') return ERROR_SEVERITY.ERROR; if (error.name === 'ReferenceError') return ERROR_SEVERITY.CRITICAL; return ERROR_SEVERITY.WARNING; } calculateRiskScore(context) { // Simplified risk calculation return Math.random() * 0.5; // Demo value } delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async retryOperation(errorRecord) { // Simplified retry logic return { success: true, retried: true }; } async activateFallback(fallback, errorRecord) { // Simplified fallback activation return { fallbackActivated: true, component: fallback }; } identifyDegradableFeatures(errorRecord) { return ['animations', 'advanced_ui', 'non_critical_apis']; } identifyEssentialFeatures(errorRecord) { return ['core_functionality', 'data_access', 'user_interface']; } async disableFeatures(features) { // Simplified feature disabling return { disabled: features }; } async ensureEssentialFeatures(features) { // Simplified essential feature check return { ensured: features }; } calculateErrorRate() { const recentErrors = this.errorHistory.filter(e => Date.now() - e.timestamp < 60000 // Last minute ); return recentErrors.length; } calculateRecoveryRate() { const recoveredErrors = this.errorHistory.filter(e => e.recovered); return this.errorHistory.length > 0 ? recoveredErrors.length / this.errorHistory.length : 0; } calculateMTTR() { const recoveredErrors = this.errorHistory.filter(e => e.recovered && e.recoveryTime); if (recoveredErrors.length === 0) return 0; const totalTime = recoveredErrors.reduce((sum, e) => sum + e.recoveryTime, 0); return totalTime / recoveredErrors.length; } calculateUserImpact(impact) { // Simplified user impact calculation return impact.severity * impact.affectedUsers; } calculateHealingSuccessRate() { const healingAttempts = this.errorHistory.filter(e => e.healingAttempted); const successfulHealing = healingAttempts.filter(e => e.healingSuccessful); return healingAttempts.length > 0 ? successfulHealing.length / healingAttempts.length : 0; } // Missing helper methods updateErrorPatterns(errorRecord) { const pattern = this.extractErrorPattern(errorRecord); const existing = this.errorPatterns.get(pattern) || { count: 0, lastSeen: 0 }; this.errorPatterns.set(pattern, { count: existing.count + 1, lastSeen: Date.now(), errorType: errorRecord.error.name || 'Unknown' }); } extractErrorPattern(errorRecord) { return `${errorRecord.error.name || 'Unknown'}_${errorRecord.context.component || 'Unknown'}`; } findKnownErrorPattern(error) { const pattern = `${error.name || 'Unknown'}_Unknown`; return this.errorPatterns.get(pattern); } getRecoveryStrategies(errorRecord) { return [ { type: RECOVERY_STRATEGIES.RETRY, maxRetries: 3, delay: 1000 }, { type: RECOVERY_STRATEGIES.FALLBACK, fallback: null }, { type: RECOVERY_STRATEGIES.GRACEFUL_DEGRADATION } ]; } recordSuccessfulStrategy(errorRecord, strategy) { // Record successful strategy for future use const pattern = this.extractErrorPattern(errorRecord); const existing = this.errorPatterns.get(pattern) || {}; existing.successfulStrategy = strategy; this.errorPatterns.set(pattern, existing); } preventiveAction(context, riskScore) { // Simplified preventive action console.warn(`High risk detected (${riskScore}), taking preventive measures`); } getHistoricalErrorData(operation) { return { errorRate: 0.1, avgRecoveryTime: 1000 }; } assessContextualRisk(context) { return 0.2; // Simplified risk assessment } combineRiskFactors(historical, contextual) { return (historical.errorRate + contextual) / 2; } classifyError(error) { return error.name || 'UnknownError'; } identifyRootCause(error, context) { return 'Unknown root cause'; } identifyAffectedSystems(error, context) { return ['component']; } selectHealingStrategy(diagnosis) { return { type: RECOVERY_STRATEGIES.RETRY, maxRetries: 2 }; } async executeHealingStrategy(strategy, diagnosis) { // Simplified healing execution return { success: true, method: strategy.type }; } recordSuccessfulHealing(diagnosis, strategy, result) { // Record successful healing for learning } escalateHealing(diagnosis, result) { // Escalate to higher level healing return { success: false, escalated: true }; } updateHealingKnowledge(learningData) { // Update healing knowledge base } handleRecoveryFailure(errorRecord, recovery) { return { success: false, reason: 'Recovery failed', errorRecord }; } handleCriticalFailure(errorRecord, recoveryError) { return { success: false, reason: 'Critical failure', errorRecord, recoveryError }; } } /** * Error Boundary Decorator */ export function withErrorBoundary(errorConfig = {}) { return function(ComponentClass) { // Handle both class and function components if (typeof ComponentClass !== 'function') { throw new Error('withErrorBoundary decorator can only be applied to classes or functions'); } // First apply principle validation const PrincipleAwareClass = withPrinciples({ enabledPrinciples: ['RESILIENCE', 'PERFORMANCE'], metadata: { hasErrorHandling: true }, ...errorConfig.principles })(ComponentClass); class ErrorBoundaryComponent extends PrincipleAwareClass { constructor(...args) { super(...args); this.errorBoundary = new AetherErrorBoundary({ fallbackComponent: this.renderErrorFallback?.bind(this), onError: this.onError?.bind(this), ...errorConfig }); this.setupErrorBoundary(); } setupErrorBoundary() { // Wrap component methods with error handling const originalMethods = ['render', 'update', 'destroy']; originalMethods.forEach(methodName => { const originalMethod = this[methodName]; if (originalMethod) { this[methodName] = async (...args) => { try { return await originalMethod.apply(this, args); } catch (error) { return this.errorBoundary.handleError(error, { method: methodName, component: this.constructor.name, args }); } }; } }); } renderErrorFallback(error, errorInfo) { return `<div class="error-fallback"> <h3>Something went wrong</h3> <p>We're working to fix this issue.</p> <button onclick="location.reload()">Reload Page</button> </div>`; } getErrorBoundaryStatus() { return this.errorBoundary.getStatus(); } } // Preserve original class name Object.defineProperty(ErrorBoundaryComponent, 'name', { value: `ErrorBoundary${ComponentClass.name}`, configurable: true }); return ErrorBoundaryComponent; }; } export default { AetherErrorBoundary, withErrorBoundary, ERROR_SEVERITY, RECOVERY_STRATEGIES };