～エラーの伝播制御とリカバリーメカニズム～

# 第18回：エラーハンドリング（後編）
## ～エラーの伝播制御とリカバリーメカニズム～

### はじめに

前回のエラー値の設計を踏まえ、今回はエラーの伝播制御とリカバリーメカニズムについて解説します。

### エラーの伝播制御

```rust
// エラー伝播コントローラー
pub struct ErrorPropagationController {
    policies: HashMap<TypeId, Box<dyn PropagationPolicy>>,
    interceptors: Vec<Box<dyn ErrorInterceptor>>,
    context_tracker: ContextTracker,
}

impl ErrorPropagationController {
    pub async fn handle_error<E: Error + 'static>(
        &self,
        error: E,
        context: &ExecutionContext,
    ) -> Result<(), E> {
        // エラーインターセプト
        for interceptor in &self.interceptors {
            if interceptor.should_intercept(&error) {
                return interceptor.handle_error(error, context).await;
            }
        }
        
        // 伝播ポリシーの適用
        if let Some(policy) = self.get_policy::<E>() {
            match policy.decide(&error) {
                PropagationDecision::Propagate => Err(error),
                PropagationDecision::Handle(handler) => handler.handle_error(error, context).await,
                PropagationDecision::Suppress => Ok(()),
            }
        } else {
            // デフォルトの伝播動作
            Err(error)
        }
    }
}

// 伝播ポリシー
pub trait PropagationPolicy: Send + Sync {
    fn decide<E: Error>(&self, error: &E) -> PropagationDecision<E>;
}

// エラーインターセプター
pub trait ErrorInterceptor: Send + Sync {
    fn should_intercept<E: Error>(&self, error: &E) -> bool;
    async fn handle_error<E: Error>(&self, error: E, context: &ExecutionContext) -> Result<(), E>;
}
```

### リカバリーメカニズム

```rust
// リカバリーマネージャー
pub struct RecoveryManager {
    strategies: Vec<Box<dyn RecoveryStrategy>>,
    state_manager: StateManager,
    recovery_log: RecoveryLog,
}

impl RecoveryManager {
    pub async fn attempt_recovery<E: Error>(
        &mut self,
        error: &E,
        context: &ExecutionContext,
    ) -> Result<(), RecoveryError> {
        // 状態の保存
        let checkpoint = self.state_manager.create_checkpoint()?;
        
        // 利用可能な回復戦略を試行
        for strategy in &self.strategies {
            if strategy.can_handle(error) {
                match strategy.recover(error, context).await {
                    Ok(()) => {
                        self.recovery_log.record_success(error, strategy.name());
                        return Ok(());
                    }
                    Err(e) => {
                        self.recovery_log.record_failure(error, strategy.name(), &e);
                        // 状態を復元して次の戦略を試行
                        self.state_manager.restore_checkpoint(checkpoint.clone())?;
                    }
                }
            }
        }
        
        Err(RecoveryError::NoValidStrategy)
    }
}

// リカバリー戦略
pub trait RecoveryStrategy: Send + Sync {
    fn name(&self) -> &str;
    fn can_handle<E: Error>(&self, error: &E) -> bool;
    async fn recover<E: Error>(&self, error: &E, context: &ExecutionContext) -> Result<(), RecoveryError>;
}

// 自動リトライ戦略
pub struct RetryStrategy {
    max_attempts: u32,
    backoff: Box<dyn BackoffStrategy>,
}

impl RecoveryStrategy for RetryStrategy {
    async fn recover<E: Error>(&self, error: &E, context: &ExecutionContext) -> Result<(), RecoveryError> {
        let mut attempts = 0;
        
        while attempts < self.max_attempts {
            match context.retry_operation().await {
                Ok(()) => return Ok(()),
                Err(_) => {
                    attempts += 1;
                    self.backoff.wait(attempts).await;
                }
            }
        }
        
        Err(RecoveryError::MaxAttemptsExceeded)
    }
}
```

### デバッグ支援

```rust
// エラーデバッグサポート
pub struct ErrorDebugSupport {
    trace_collector: TraceCollector,
    analyzer: ErrorAnalyzer,
    reporter: ErrorReporter,
}

impl ErrorDebugSupport {
    pub async fn analyze_error<E: Error>(
        &self,
        error: &E,
        context: &ExecutionContext,
    ) -> DebugReport {
        // エラートレースの収集
        let trace = self.trace_collector.collect_trace(error, context).await?;
        
        // エラーの分析
        let analysis = self.analyzer.analyze(&trace)?;
        
        // レポートの生成
        self.reporter.generate_report(analysis)
    }
}

// トレース収集
pub struct TraceCollector {
    collectors: Vec<Box<dyn TraceCollectorPlugin>>,
}

impl TraceCollector {
    pub async fn collect_trace<E: Error>(
        &self,
        error: &E,
        context: &ExecutionContext,
    ) -> Result<ErrorTrace> {
        let mut trace = ErrorTrace::new(error);
        
        for collector in &self.collectors {
            collector.collect_information(&mut trace, context).await?;
        }
        
        Ok(trace)
    }
}
```

### 実装例：エラーリカバリーシステムの実装

```rust
// エラーリカバリーシステムの実装例
pub struct ErrorRecoverySystem {
    propagation_controller: ErrorPropagationController,
    recovery_manager: RecoveryManager,
    debug_support: ErrorDebugSupport,
}

impl ErrorRecoverySystem {
    pub async fn handle_error<E: Error + 'static>(
        &mut self,
        error: E,
        context: &ExecutionContext,
    ) -> Result<(), E> {
        // エラーの伝播制御
        if let Err(error) = self.propagation_controller.handle_error(error, context).await {
            // リカバリーの試行
            if let Err(recovery_error) = self.recovery_manager.attempt_recovery(&error, context).await {
                // リカバリー失敗時のデバッグ情報収集
                let debug_report = self.debug_support.analyze_error(&error, context).await?;
                log::error!("Recovery failed: {:?}\nDebug report: {:?}", recovery_error, debug_report);
                return Err(error);
            }
        }
        Ok(())
    }
}

// 使用例
async fn example_usage() -> Result<(), AppError> {
    let mut system = ErrorRecoverySystem::new();
    
    // リカバリー戦略の登録
    system.recovery_manager.add_strategy(Box::new(RetryStrategy::new(3)));
    system.recovery_manager.add_strategy(Box::new(FallbackStrategy::new()));
    
    // エラーが発生する可能性のある操作
    let result = complex_operation().await;
    
    match result {
        Ok(value) => Ok(value),
        Err(error) => {
            let context = ExecutionContext::current();
            system.handle_error(error, &context).await
        }
    }
}

// リカバリー可能な操作の例
async fn complex_operation() -> Result<(), AppError> {
    let mut recovery_points = Vec::new();
    
    // 操作の実行
    for step in operation_steps() {
        if step.is_critical() {
            // 重要なステップの前にリカバリーポイントを作成
            recovery_points.push(create_recovery_point().await?);
        }
        
        match step.execute().await {
            Ok(()) => continue,
            Err(error) => {
                // エラー発生時の回復処理
                if let Some(point) = recovery_points.last() {
                    restore_recovery_point(point).await?;
                    // 再試行ロジック
                }
                return Err(error.into());
            }
        }
    }
    
    Ok(())
}
```

### 今回のまとめ

1. 効果的なエラー伝播制御の実装
2. 柔軟なリカバリーメカニズム
3. 包括的なデバッグ支援
4. 実用的なエラーリカバリーシステム

### 次回予告

第19回では、型システムの応用について解説します。状態遷移の型安全な表現と依存型のエミュレーションについて詳しく見ていきます。

### 参考資料
- Advanced Error Handling Patterns
- System Recovery Strategies
- Debugging Distributed Systems
- Resilient Error Management