glassbox-ai
Version:
Enterprise-grade AI testing framework with reliability, observability, and comprehensive validation
393 lines (343 loc) • 11.8 kB
JavaScript
/**
* Reliability Manager - Main orchestrator for enterprise-grade reliability
* Integrates all reliability features into a unified system
*/
import { ExponentialBackoff } from './exponential-backoff.js';
import { CircuitBreaker } from './circuit-breaker.js';
import { FallbackManager } from './fallback-manager.js';
import { HealthChecker } from './health-checker.js';
import { MetricsCollector } from './metrics-collector.js';
import { RequestQueue } from './request-queue.js';
import { GracefulShutdown } from './graceful-shutdown.js';
export class ReliabilityManager {
constructor(options = {}) {
// Initialize all reliability components
this.exponentialBackoff = new ExponentialBackoff(options.backoff || {});
this.circuitBreakers = new Map();
this.fallbackManager = new FallbackManager(options.fallback || {});
this.healthChecker = new HealthChecker(options.health || {});
this.metrics = new MetricsCollector(options.metrics || {});
this.requestQueue = new RequestQueue(options.queue || {});
this.gracefulShutdown = new GracefulShutdown(options.shutdown || {});
// Configuration
this.enabled = options.enabled !== false;
this.autoStart = options.autoStart !== false;
// Service registry
this.services = new Map();
this.serviceConfigs = new Map();
// Auto-start if enabled
if (this.autoStart) {
this.start();
}
}
/**
* Start all reliability components
*/
start() {
if (!this.enabled) return;
console.log('Starting enterprise reliability system...');
// Start health monitoring
this.healthChecker.start();
// Start metrics collection
this.metrics.startExport();
// Register shutdown hooks
this.setupShutdownHooks();
console.log('Enterprise reliability system started');
}
/**
* Stop all reliability components
*/
stop() {
console.log('Stopping enterprise reliability system...');
this.healthChecker.stop();
this.metrics.stopExport();
this.requestQueue.clear();
console.log('Enterprise reliability system stopped');
}
/**
* Register a service with reliability features
* @param {string} serviceName - Service name
* @param {Function} primaryFn - Primary service function
* @param {Array<Function>} fallbacks - Fallback functions
* @param {object} options - Service options
*/
registerService(serviceName, primaryFn, fallbacks = [], options = {}) {
const config = {
circuitBreaker: {
failureThreshold: 5,
successThreshold: 2,
timeout: 60000,
...options.circuitBreaker
},
backoff: {
maxAttempts: 3,
baseDelay: 1000,
...options.backoff
},
health: {
checkInterval: 30000,
timeout: 10000,
...options.health
},
queue: {
priority: 0,
timeout: 30000,
...options.queue
},
metrics: {
enabled: true,
...options.metrics
},
...options
};
// Create circuit breaker for this service
const circuitBreaker = new CircuitBreaker(config.circuitBreaker);
this.circuitBreakers.set(serviceName, circuitBreaker);
// Register with fallback manager
this.fallbackManager.registerService(serviceName, primaryFn, fallbacks, {
strategy: config.fallbackStrategy || 'sequential',
timeout: config.queue.timeout
});
// Register health check
this.healthChecker.registerCheck(`${serviceName}_health`, async () => {
try {
await this.executeWithReliability(serviceName, () => Promise.resolve('healthy'));
return { status: 'healthy' };
} catch (error) {
throw new Error(`Service health check failed: ${error.message}`);
}
}, {
timeout: config.health.timeout,
critical: config.health.critical || false
});
// Store service configuration
this.serviceConfigs.set(serviceName, config);
this.services.set(serviceName, primaryFn);
console.log(`Registered service '${serviceName}' with reliability features`);
}
/**
* Execute a service with all reliability features
* @param {string} serviceName - Service name
* @param {Array} args - Service arguments
* @param {object} options - Execution options
* @returns {Promise<any>} Service result
*/
async executeWithReliability(serviceName, args = [], options = {}) {
if (!this.enabled) {
// Execute without reliability features
const service = this.services.get(serviceName);
if (!service) {
throw new Error(`Service '${serviceName}' not registered`);
}
return await service(...args);
}
const config = this.serviceConfigs.get(serviceName);
const circuitBreaker = this.circuitBreakers.get(serviceName);
if (!config || !circuitBreaker) {
throw new Error(`Service '${serviceName}' not registered with reliability features`);
}
// Create the execution function with all reliability layers
const executeFn = async () => {
return await this.metrics.timeAsync(`${serviceName}_execution`, async () => {
// Execute with circuit breaker
return await circuitBreaker.execute(async () => {
// Execute with fallback manager
const result = await this.fallbackManager.execute(serviceName, args, options);
return result.result;
}, {
fallback: (error) => {
this.metrics.increment(`${serviceName}_circuit_breaker_failures`);
throw error;
}
});
}, { service: serviceName });
};
// Add to request queue if enabled
if (config.queue.enabled !== false) {
return await this.requestQueue.add(executeFn, {
priority: config.queue.priority,
timeout: config.queue.timeout
});
} else {
return await executeFn();
}
}
/**
* Execute with exponential backoff retry
* @param {string} serviceName - Service name
* @param {Array} args - Service arguments
* @param {object} options - Retry options
* @returns {Promise<any>} Service result
*/
async executeWithRetry(serviceName, args = [], options = {}) {
const config = this.serviceConfigs.get(serviceName);
const backoffConfig = { ...this.exponentialBackoff, ...config?.backoff, ...options };
return await this.exponentialBackoff.execute(async () => {
return await this.executeWithReliability(serviceName, args, options);
}, backoffConfig);
}
/**
* Get service health status
* @param {string} serviceName - Service name
* @returns {object} Health status
*/
getServiceHealth(serviceName) {
const circuitBreaker = this.circuitBreakers.get(serviceName);
const healthStatus = this.healthChecker.getCheckStatus(`${serviceName}_health`);
const serviceInfo = this.fallbackManager.getServiceInfo(serviceName);
return {
serviceName,
circuitBreaker: circuitBreaker ? circuitBreaker.getState() : null,
health: healthStatus,
fallback: serviceInfo,
metrics: this.getServiceMetrics(serviceName)
};
}
/**
* Get service metrics
* @param {string} serviceName - Service name
* @returns {object} Service metrics
*/
getServiceMetrics(serviceName) {
const metrics = this.metrics.getAllMetrics();
const serviceMetrics = {};
// Filter metrics for this service
for (const [key, value] of Object.entries(metrics.histograms)) {
if (key.includes(serviceName)) {
serviceMetrics[key] = value;
}
}
for (const [key, value] of Object.entries(metrics.counters)) {
if (key.includes(serviceName)) {
serviceMetrics[key] = value;
}
}
return serviceMetrics;
}
/**
* Get overall system health
* @returns {object} System health status
*/
getSystemHealth() {
return {
overall: this.healthChecker.getOverallHealth(),
services: Array.from(this.services.keys()).map(name => this.getServiceHealth(name)),
queue: this.requestQueue.getStatus(),
metrics: this.metrics.getSummary(),
shutdown: this.gracefulShutdown.getStatus()
};
}
/**
* Get comprehensive system metrics
* @returns {object} System metrics
*/
getSystemMetrics() {
return {
metrics: this.metrics.getAllMetrics(),
performance: this.metrics.getPerformanceMetrics(),
queue: this.requestQueue.getMetrics(),
health: this.healthChecker.getMetrics(),
services: Array.from(this.services.keys()).reduce((acc, name) => {
acc[name] = this.getServiceMetrics(name);
return acc;
}, {})
};
}
/**
* Setup shutdown hooks for cleanup
*/
setupShutdownHooks() {
// Register cleanup tasks
this.gracefulShutdown.registerCleanupTask('stop_health_checker', () => {
this.healthChecker.stop();
}, { priority: 1 });
this.gracefulShutdown.registerCleanupTask('stop_metrics', () => {
this.metrics.stopExport();
}, { priority: 2 });
this.gracefulShutdown.registerCleanupTask('clear_queue', () => {
this.requestQueue.clear();
}, { priority: 3 });
// Register shutdown hooks
this.gracefulShutdown.registerShutdownHook(async () => {
console.log('Exporting final metrics...');
this.metrics.exportMetrics();
}, { priority: 1 });
this.gracefulShutdown.registerShutdownHook(async () => {
console.log('Generating final health report...');
const health = this.getSystemHealth();
console.log('Final system health:', JSON.stringify(health, null, 2));
}, { priority: 2 });
}
/**
* Test reliability features
* @param {string} serviceName - Service to test
* @returns {Promise<object>} Test results
*/
async testReliability(serviceName) {
const results = {
serviceName,
circuitBreaker: null,
health: null,
fallback: null,
metrics: null,
queue: null,
success: true
};
try {
// Test circuit breaker
const circuitBreaker = this.circuitBreakers.get(serviceName);
if (circuitBreaker) {
results.circuitBreaker = circuitBreaker.getState();
}
// Test health check
const healthStatus = this.healthChecker.getCheckStatus(`${serviceName}_health`);
results.health = healthStatus;
// Test fallback
const fallbackInfo = this.fallbackManager.getServiceInfo(serviceName);
results.fallback = fallbackInfo;
// Test metrics
results.metrics = this.getServiceMetrics(serviceName);
// Test queue
results.queue = this.requestQueue.getStatus();
} catch (error) {
results.success = false;
results.error = error.message;
}
return results;
}
/**
* Enable reliability features
*/
enable() {
this.enabled = true;
console.log('Reliability features enabled');
}
/**
* Disable reliability features
*/
disable() {
this.enabled = false;
console.log('Reliability features disabled');
}
/**
* Get reliability configuration
* @returns {object} Configuration
*/
getConfiguration() {
return {
enabled: this.enabled,
autoStart: this.autoStart,
services: Array.from(this.serviceConfigs.keys()),
serviceConfigs: Object.fromEntries(this.serviceConfigs),
components: {
exponentialBackoff: this.exponentialBackoff,
circuitBreakers: this.circuitBreakers.size,
fallbackManager: this.fallbackManager.getAllServices(),
healthChecker: this.healthChecker.getOverallHealth(),
metrics: this.metrics.getSummary(),
requestQueue: this.requestQueue.getStatus(),
gracefulShutdown: this.gracefulShutdown.getStatus()
}
};
}
}