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
JavaScript
"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