UNPKG

datapilot-cli

Version:

Enterprise-grade streaming multi-format data analysis with comprehensive statistical insights and intelligent relationship detection - supports CSV, JSON, Excel, TSV, Parquet - memory-efficient, cross-platform

407 lines 16.1 kB
"use strict"; /** * Graceful Degradation Framework * Provides intelligent fallback strategies for analysis failures */ Object.defineProperty(exports, "__esModule", { value: true }); exports.globalDegradationEngine = exports.GracefulDegradationEngine = exports.DegradationLevel = void 0; const logger_1 = require("../utils/logger"); var DegradationLevel; (function (DegradationLevel) { DegradationLevel[DegradationLevel["NONE"] = 0] = "NONE"; DegradationLevel[DegradationLevel["MINIMAL"] = 1] = "MINIMAL"; DegradationLevel[DegradationLevel["MODERATE"] = 2] = "MODERATE"; DegradationLevel[DegradationLevel["AGGRESSIVE"] = 3] = "AGGRESSIVE"; DegradationLevel[DegradationLevel["EMERGENCY"] = 4] = "EMERGENCY"; })(DegradationLevel || (exports.DegradationLevel = DegradationLevel = {})); /** * Main Graceful Degradation Engine */ class GracefulDegradationEngine { strategies = new Map(); currentLevel = DegradationLevel.NONE; appliedStrategies = []; constructor() { this.initializeDefaultStrategies(); } /** * Evaluate context and determine appropriate degradation level */ assessDegradationNeeds(context) { logger_1.logger.debug('Assessing degradation needs', { context }); // Check memory pressure if (context.availableMemoryMB < 100) { return DegradationLevel.EMERGENCY; } if (context.availableMemoryMB < 256) { return DegradationLevel.AGGRESSIVE; } if (context.availableMemoryMB < 512) { return DegradationLevel.MODERATE; } // Check processing time if (context.processingTimeMs > 300000) { // 5 minutes return DegradationLevel.MODERATE; } // Check error history if (context.errorHistory.length > 10) { return DegradationLevel.AGGRESSIVE; } if (context.errorHistory.length > 5) { return DegradationLevel.MODERATE; } // Check data quality if (context.dataQualityScore < 30) { return DegradationLevel.MODERATE; } if (context.dataQualityScore < 50) { return DegradationLevel.MINIMAL; } return DegradationLevel.NONE; } /** * Apply degradation strategies based on context */ applyDegradation(context, analysisFunction) { return this.executeWithDegradation(context, analysisFunction); } /** * Execute analysis with progressive degradation */ async executeWithDegradation(context, analysisFunction) { const targetLevel = this.assessDegradationNeeds(context); this.currentLevel = targetLevel; this.appliedStrategies = []; logger_1.logger.info(`Applying degradation level: ${DegradationLevel[targetLevel]}`); try { // Apply pre-analysis degradation strategies this.applyPreAnalysisStrategies(targetLevel, context); // Attempt analysis with current strategies const result = await this.attemptAnalysisWithFallbacks(analysisFunction, context); return { result, degradationLevel: this.currentLevel, appliedStrategies: this.appliedStrategies, completedSections: this.getCompletedSections(result), failedSections: [], partialSections: this.getPartialSections(result), qualityRetained: this.calculateQualityRetention(), userGuidance: this.generateUserGuidance(), recoveryOptions: this.generateRecoveryOptions(context), }; } catch (error) { logger_1.logger.error('Analysis failed with degradation', { error, level: this.currentLevel }); return this.handleCompleteFailure(error, context); } } /** * Attempt analysis with progressive fallbacks */ async attemptAnalysisWithFallbacks(analysisFunction, context) { const maxAttempts = 3; let currentAttempt = 0; let lastError = null; while (currentAttempt < maxAttempts) { try { logger_1.logger.debug(`Analysis attempt ${currentAttempt + 1}/${maxAttempts}`); const result = await analysisFunction(); logger_1.logger.info(`Analysis succeeded on attempt ${currentAttempt + 1}`); return result; } catch (error) { lastError = error; currentAttempt++; logger_1.logger.warn(`Analysis attempt ${currentAttempt} failed`, { error }); if (currentAttempt < maxAttempts) { // Escalate degradation for next attempt this.escalateDegradation(context); } } } // All attempts failed, return partial results if possible throw lastError || new Error('Analysis failed after all attempts'); } /** * Apply strategies before analysis begins */ applyPreAnalysisStrategies(level, context) { const strategies = this.getStrategiesForLevel(level); for (const strategy of strategies) { if (this.shouldApplyStrategy(strategy, context)) { this.applyStrategy(strategy); this.appliedStrategies.push(strategy); } } } /** * Check if strategy should be applied */ shouldApplyStrategy(strategy, context) { const trigger = strategy.trigger; if (trigger.memoryThresholdMB && context.availableMemoryMB >= trigger.memoryThresholdMB) { return false; } if (trigger.processingTimeThresholdMs && context.processingTimeMs < trigger.processingTimeThresholdMs) { return false; } if (trigger.errorCountThreshold && context.errorHistory.length < trigger.errorCountThreshold) { return false; } if (trigger.dataQualityThreshold && context.dataQualityScore >= trigger.dataQualityThreshold) { return false; } return true; } /** * Apply specific degradation strategy */ applyStrategy(strategy) { logger_1.logger.info(`Applying degradation strategy: ${strategy.userMessage}`); for (const action of strategy.actions) { this.executeAction(action); } } /** * Execute degradation action */ executeAction(action) { logger_1.logger.debug(`Executing degradation action: ${action.type} on ${action.target}`); switch (action.type) { case 'disable_feature': this.disableFeature(action.target); break; case 'reduce_scope': this.reduceScope(action.target, action.parameters); break; case 'simplify_algorithm': this.simplifyAlgorithm(action.target, action.parameters); break; case 'skip_optional': this.skipOptional(action.target); break; case 'use_sampling': this.enableSampling(action.target, action.parameters); break; } } /** * Escalate degradation level for retry */ escalateDegradation(context) { if (this.currentLevel < DegradationLevel.EMERGENCY) { this.currentLevel++; logger_1.logger.info(`Escalating degradation to level: ${DegradationLevel[this.currentLevel]}`); this.applyPreAnalysisStrategies(this.currentLevel, context); } } /** * Handle complete analysis failure */ handleCompleteFailure(error, context) { logger_1.logger.error('Complete analysis failure', { error: error.message }); return { result: {}, degradationLevel: DegradationLevel.EMERGENCY, appliedStrategies: this.appliedStrategies, completedSections: [], failedSections: ['all'], partialSections: [], qualityRetained: 0, userGuidance: 'Analysis failed completely. Please try with smaller data or reduced settings.', recoveryOptions: this.generateEmergencyRecoveryOptions(error, context), }; } /** * Initialize default degradation strategies */ initializeDefaultStrategies() { // Minimal degradation - reduce optional features this.strategies.set('minimal', { level: DegradationLevel.MINIMAL, trigger: { memoryThresholdMB: 512, dataQualityThreshold: 70 }, actions: [ { type: 'skip_optional', target: 'advanced_statistics', impact: 'Some advanced statistical measures will be skipped', }, { type: 'reduce_scope', target: 'correlation_analysis', parameters: { maxPairs: 20 }, impact: 'Correlation analysis limited to top 20 pairs', }, ], fallbackAnalyses: ['basic_statistics', 'data_quality'], qualityImpact: 10, userMessage: 'Using simplified analysis to optimize performance', }); // Moderate degradation - significant scope reduction this.strategies.set('moderate', { level: DegradationLevel.MODERATE, trigger: { memoryThresholdMB: 256, errorCountThreshold: 5, dataQualityThreshold: 50 }, actions: [ { type: 'disable_feature', target: 'multivariate_analysis', impact: 'Multivariate analysis disabled', }, { type: 'use_sampling', target: 'large_datasets', parameters: { sampleSize: 5000 }, impact: 'Analysis limited to 5,000 row sample', }, { type: 'simplify_algorithm', target: 'clustering', parameters: { algorithm: 'kmeans_simple' }, impact: 'Using simplified clustering algorithm', }, ], fallbackAnalyses: ['univariate_analysis', 'basic_quality'], qualityImpact: 30, userMessage: 'Using reduced analysis scope due to resource constraints', }); // Aggressive degradation - minimal analysis only this.strategies.set('aggressive', { level: DegradationLevel.AGGRESSIVE, trigger: { memoryThresholdMB: 128, errorCountThreshold: 10 }, actions: [ { type: 'disable_feature', target: 'visualization_recommendations', impact: 'Visualization recommendations disabled', }, { type: 'disable_feature', target: 'engineering_recommendations', impact: 'Engineering recommendations disabled', }, { type: 'use_sampling', target: 'all_analysis', parameters: { sampleSize: 1000 }, impact: 'Analysis limited to 1,000 row sample', }, ], fallbackAnalyses: ['basic_overview', 'simple_quality'], qualityImpact: 60, userMessage: 'Using minimal analysis due to severe resource constraints', }); // Emergency degradation - absolute minimum this.strategies.set('emergency', { level: DegradationLevel.EMERGENCY, trigger: { memoryThresholdMB: 64 }, actions: [ { type: 'disable_feature', target: 'all_advanced_features', impact: 'All advanced features disabled', }, { type: 'use_sampling', target: 'emergency_sample', parameters: { sampleSize: 100 }, impact: 'Analysis limited to 100 row sample', }, ], fallbackAnalyses: ['file_overview_only'], qualityImpact: 90, userMessage: 'Emergency mode: providing minimal file overview only', }); } // Helper methods for strategy application disableFeature(feature) { // Implementation would disable specific features logger_1.logger.debug(`Disabling feature: ${feature}`); } reduceScope(target, parameters) { // Implementation would reduce analysis scope logger_1.logger.debug(`Reducing scope for: ${target}`, { parameters }); } simplifyAlgorithm(target, parameters) { // Implementation would use simpler algorithms logger_1.logger.debug(`Simplifying algorithm for: ${target}`, { parameters }); } skipOptional(target) { // Implementation would skip optional analysis logger_1.logger.debug(`Skipping optional: ${target}`); } enableSampling(target, parameters) { // Implementation would enable data sampling logger_1.logger.debug(`Enabling sampling for: ${target}`, { parameters }); } getStrategiesForLevel(level) { return Array.from(this.strategies.values()).filter((s) => s.level <= level); } getCompletedSections(result) { // Implementation would determine completed sections return Object.keys(result); } getPartialSections(result) { // Implementation would determine partial sections return []; } calculateQualityRetention() { const totalImpact = this.appliedStrategies.reduce((sum, s) => sum + s.qualityImpact, 0); return Math.max(0, 100 - totalImpact); } generateUserGuidance() { if (this.appliedStrategies.length === 0) { return 'Analysis completed successfully with full features.'; } const messages = this.appliedStrategies.map((s) => s.userMessage); return `Analysis completed with adaptations: ${messages.join('; ')}.`; } generateRecoveryOptions(context) { const options = []; if (context.availableMemoryMB < 512) { options.push({ description: 'Increase available memory or reduce dataset size', action: 'adjust_settings', command: 'datapilot --memory-limit 2GB', automated: false, estimatedTime: '2-5 minutes', successProbability: 80, }); } if (this.currentLevel > DegradationLevel.MINIMAL) { options.push({ description: 'Retry with reduced scope', action: 'retry', command: 'datapilot --scope basic', automated: true, estimatedTime: '1-2 minutes', successProbability: 90, }); } return options; } generateEmergencyRecoveryOptions(error, context) { return [ { description: 'Try with a smaller data sample', action: 'reduce_data', command: 'head -n 1000 your-file.csv > sample.csv && datapilot sample.csv', automated: false, estimatedTime: '30 seconds', successProbability: 95, }, { description: 'Contact support with error details', action: 'contact_support', automated: false, estimatedTime: '24-48 hours', successProbability: 100, }, ]; } } exports.GracefulDegradationEngine = GracefulDegradationEngine; // Global instance exports.globalDegradationEngine = new GracefulDegradationEngine(); //# sourceMappingURL=graceful-degradation.js.map