UNPKG

@sailboat-computer/health-monitoring

Version:

Comprehensive health monitoring system for sailboat computer v3 with marine-specific health checks

628 lines (537 loc) 12.2 kB
/** * Recovery action types and interfaces for self-healing mechanisms */ import { HealthStatus, HealthStatusType, OperationalContext, OperationalContextType, MarineSystemType, MarineSystemTypeType, MarineEnvironmentStatus, HealthCheckResult } from '../types'; /** * Recovery action types */ export enum RecoveryActionType { /** * Restart a component or service */ RESTART = 'restart', /** * Switch to a backup system */ FAILOVER = 'failover', /** * Reset a component to default settings */ RESET = 'reset', /** * Recalibrate a sensor or component */ RECALIBRATE = 'recalibrate', /** * Adjust configuration parameters */ ADJUST_CONFIG = 'adjust_config', /** * Reduce load on a system */ REDUCE_LOAD = 'reduce_load', /** * Isolate a component from the system */ ISOLATE = 'isolate', /** * Notify crew for manual intervention */ NOTIFY = 'notify' } /** * Recovery action priority */ export enum RecoveryPriority { /** * Low priority, can be delayed */ LOW = 'low', /** * Normal priority */ NORMAL = 'normal', /** * High priority, execute soon */ HIGH = 'high', /** * Critical priority, execute immediately */ CRITICAL = 'critical' } /** * Recovery action status */ export enum RecoveryStatus { /** * Action is pending execution */ PENDING = 'pending', /** * Action is currently executing */ EXECUTING = 'executing', /** * Action completed successfully */ SUCCEEDED = 'succeeded', /** * Action failed */ FAILED = 'failed', /** * Action was cancelled */ CANCELLED = 'cancelled', /** * Action timed out */ TIMEOUT = 'timeout' } /** * Recovery action configuration */ export interface RecoveryActionConfig { /** * Unique ID for this recovery action */ actionId: string; /** * Human-readable name */ name: string; /** * Type of recovery action */ type: RecoveryActionType; /** * System type this action applies to */ marineSystemType: MarineSystemTypeType; /** * Priority of this action */ priority: RecoveryPriority; /** * Maximum execution time in ms */ timeout: number; /** * Maximum number of retry attempts */ maxRetries: number; /** * Delay between retries in ms */ retryDelay: number; /** * Whether this action requires manual approval */ requiresApproval: boolean; /** * Whether this action can run in automated mode */ automatedExecution: boolean; /** * Marine-specific settings */ marineSettings: { /** * Operational contexts where this action is allowed */ allowedContexts: OperationalContextType[]; /** * Whether this action is allowed in rough sea conditions */ allowInRoughSeas: boolean; /** * Whether this action is power-aware */ powerAware: boolean; /** * Whether this action affects vessel safety */ safetyImpact: boolean; /** * Estimated power consumption in watts */ powerConsumption: number; }; /** * Action-specific parameters */ parameters: Record<string, any>; } /** * Recovery action result */ export interface RecoveryActionResult { /** * Action ID */ actionId: string; /** * Action name */ name: string; /** * Action type */ type: RecoveryActionType; /** * Execution status */ status: RecoveryStatus; /** * Result message */ message: string; /** * Start time */ startTime: Date; /** * End time */ endTime: Date; /** * Execution duration in ms */ duration: number; /** * Number of retry attempts */ retryCount: number; /** * Whether the action was successful */ success: boolean; /** * Error details if failed */ error?: string; /** * Action-specific result details */ details?: Record<string, any>; /** * Marine context during execution */ marineContext: { operationalContext: OperationalContextType; environmentalConditions?: Partial<MarineEnvironmentStatus> | undefined; }; /** * Health check that triggered this action */ triggeringCheck?: { checkId: string; status: HealthStatusType; score: number; } | undefined; /** * Health check result after recovery attempt */ resultingCheck?: { checkId: string; status: HealthStatusType; score: number; }; } /** * Recovery policy */ export interface RecoveryPolicy { /** * Policy ID */ policyId: string; /** * Human-readable name */ name: string; /** * Health check ID this policy applies to */ checkId: string; /** * Marine system type */ marineSystemType: MarineSystemTypeType; /** * Health status threshold to trigger recovery */ triggerStatus: HealthStatusType; /** * Health score threshold to trigger recovery */ triggerScore: number; /** * Number of consecutive failures before triggering */ consecutiveFailures: number; /** * Recovery actions to attempt, in order */ actions: string[]; /** * Whether to stop after first successful action */ stopOnSuccess: boolean; /** * Whether this policy is enabled */ enabled: boolean; /** * Cooldown period between recovery attempts in ms */ cooldownPeriod: number; /** * Maximum number of recovery attempts in a time window */ maxAttempts: number; /** * Time window for max attempts in ms */ attemptWindow: number; /** * Marine-specific settings */ marineSettings: { /** * Operational contexts where this policy is active */ activeContexts: OperationalContextType[]; /** * Whether to apply in rough sea conditions */ activeInRoughSeas: boolean; /** * Whether this policy is power-aware */ powerAware: boolean; /** * Whether this policy affects vessel safety */ safetyImpact: boolean; }; } /** * Recovery event */ export interface RecoveryEvent { /** * Event ID */ eventId: string; /** * Timestamp */ timestamp: Date; /** * Event type */ eventType: 'recovery_started' | 'recovery_completed' | 'recovery_failed' | 'policy_triggered' | 'action_executed'; /** * System ID */ systemId: string; /** * Check ID that triggered recovery */ checkId?: string; /** * Policy ID */ policyId?: string; /** * Action ID */ actionId?: string; /** * Event data */ data: { message: string; details?: Record<string, any> | undefined; marineContext: { operationalContext: OperationalContextType; environmentalConditions?: Partial<MarineEnvironmentStatus> | undefined; }; }; /** * Recovery result */ result?: RecoveryActionResult; } /** * Abstract base class for recovery actions */ export abstract class BaseRecoveryAction { protected config: RecoveryActionConfig; protected lastResult?: RecoveryActionResult; protected retryCount = 0; constructor(config: RecoveryActionConfig) { this.config = config; } /** * Execute the recovery action */ async execute( triggeringCheck: HealthCheckResult, operationalContext: OperationalContextType, marineEnvironment?: MarineEnvironmentStatus ): Promise<RecoveryActionResult> { const startTime = new Date(); try { // Check if action is allowed in current context if (!this.isAllowedInContext(operationalContext, marineEnvironment)) { return this.createFailedResult( startTime, new Date(), 'Action not allowed in current operational context', operationalContext, marineEnvironment, triggeringCheck ); } // Execute the actual recovery action const result = await this.performRecovery(triggeringCheck, operationalContext, marineEnvironment); const endTime = new Date(); if (result.success) { this.retryCount = 0; this.lastResult = result; return { ...result, startTime, endTime, duration: endTime.getTime() - startTime.getTime(), retryCount: this.retryCount, triggeringCheck: { checkId: triggeringCheck.checkId, status: triggeringCheck.status, score: triggeringCheck.score } }; } else { // Handle retry logic if (this.retryCount < this.config.maxRetries) { this.retryCount++; await new Promise(resolve => setTimeout(resolve, this.config.retryDelay)); return this.execute(triggeringCheck, operationalContext, marineEnvironment); } else { // Max retries reached const failedResult = this.createFailedResult( startTime, new Date(), `Recovery action failed after ${this.retryCount} retries: ${result.message}`, operationalContext, marineEnvironment, triggeringCheck ); this.lastResult = failedResult; return failedResult; } } } catch (error) { const failedResult = this.createFailedResult( startTime, new Date(), `Recovery action error: ${(error as Error).message}`, operationalContext, marineEnvironment, triggeringCheck ); this.lastResult = failedResult; return failedResult; } } /** * Get the last execution result */ getLastResult(): RecoveryActionResult | undefined { return this.lastResult; } /** * Get action configuration */ getConfig(): RecoveryActionConfig { return { ...this.config }; } /** * Check if action is allowed in current context */ protected isAllowedInContext( operationalContext: OperationalContextType, marineEnvironment?: MarineEnvironmentStatus ): boolean { // Check operational context if (!this.config.marineSettings.allowedContexts.includes(operationalContext)) { return false; } // Check sea conditions if (marineEnvironment?.seaState === 'rough' || marineEnvironment?.seaState === 'very_rough') { if (!this.config.marineSettings.allowInRoughSeas) { return false; } } // Check power status if (this.config.marineSettings.powerAware && marineEnvironment?.powerStatus === 'critical') { // Only allow safety-critical actions when power is critical return this.config.marineSettings.safetyImpact; } return true; } /** * Create a failed result */ protected createFailedResult( startTime: Date, endTime: Date, message: string, operationalContext: OperationalContextType, marineEnvironment?: MarineEnvironmentStatus, triggeringCheck?: HealthCheckResult ): RecoveryActionResult { return { actionId: this.config.actionId, name: this.config.name, type: this.config.type, status: RecoveryStatus.FAILED, message, startTime, endTime, duration: endTime.getTime() - startTime.getTime(), retryCount: this.retryCount, success: false, error: message, marineContext: { operationalContext, environmentalConditions: marineEnvironment ? { ...marineEnvironment } : undefined }, triggeringCheck: triggeringCheck ? { checkId: triggeringCheck.checkId, status: triggeringCheck.status, score: triggeringCheck.score } : undefined }; } /** * Abstract method to perform the actual recovery action */ protected abstract performRecovery( triggeringCheck: HealthCheckResult, operationalContext: OperationalContextType, marineEnvironment?: MarineEnvironmentStatus ): Promise<RecoveryActionResult>; }