～Erlang型の堅牢な開発環境の実現～

# 第4回：cusinart - 分散デバッグとホットリロード
## ～Erlang型の堅牢な開発環境の実現～

### はじめに

分散システムのデバッグと動的更新は従来大きな課題でした。cusinartでは、Erlangのようなホットリロードとデバッグのサポートにより、この課題を解決します。

### 組込みデバッガーの設計

```rust
// デバッガーの基本構造
pub struct CusinartDebugger {
    breakpoints: HashMap<SourceLocation, Breakpoint>,
    variables: VariableInspector,
    stack_trace: StackTracer,
    remote_sessions: HashMap<NodeId, RemoteDebugSession>,
}

impl CusinartDebugger {
    pub fn set_breakpoint(&mut self, location: SourceLocation, condition: Option<BreakCondition>) -> Result<()> {
        let breakpoint = Breakpoint {
            location,
            condition,
            hit_count: 0,
            enabled: true,
        };
        self.breakpoints.insert(location, breakpoint);
        
        // 全リモートノードに伝播
        for session in self.remote_sessions.values() {
            session.sync_breakpoint(&breakpoint)?;
        }
        Ok(())
    }

    pub async fn inspect_variable(&self, name: &str, frame: StackFrame) -> Result<Value> {
        let value = self.variables.get_value(name, frame)?;
        
        // 必要に応じてリモートノードから値を取得
        if value.is_remote() {
            let node_id = value.node_id();
            let remote_value = self.remote_sessions
                .get(&node_id)
                .ok_or(Error::NodeNotFound)?
                .fetch_variable(name)
                .await?;
            Ok(remote_value)
        } else {
            Ok(value)
        }
    }
}

// スタックトレース解析
pub struct StackTracer {
    frames: Vec<StackFrame>,
    source_map: SourceMap,
}

impl StackTracer {
    pub fn capture_trace(&mut self) -> Result<Vec<StackFrame>> {
        let backtrace = Backtrace::capture();
        let frames = backtrace.frames()
            .iter()
            .filter_map(|frame| self.source_map.resolve_frame(frame))
            .collect();
        Ok(frames)
    }
    
    pub fn get_current_location(&self) -> Option<SourceLocation> {
        self.frames.last().map(|frame| frame.location.clone())
    }
}
```

### Erlang型ホットリロードの実装

```rust
// コード更新管理
pub struct HotReloadManager {
    modules: HashMap<ModuleId, ModuleVersion>,
    state_migrations: Vec<StateMigration>,
    active_processes: ProcessTracker,
}

impl HotReloadManager {
    pub async fn reload_module(&mut self, module: Module) -> Result<()> {
        let old_version = self.modules.get(&module.id()).cloned();
        let new_version = ModuleVersion::new(module.clone());
        
        // 安全性チェック
        self.verify_compatibility(&old_version, &new_version)?;
        
        // 状態移行の準備
        if let Some(old) = old_version {
            let migration = StateMigration::prepare(&old, &new_version)?;
            self.state_migrations.push(migration);
        }
        
        // モジュールの更新
        self.modules.insert(module.id(), new_version);
        
        // アクティブなプロセスの更新
        self.active_processes.update_module(module).await?;
        
        Ok(())
    }
    
    fn verify_compatibility(&self, old: &Option<ModuleVersion>, new: &ModuleVersion) -> Result<()> {
        if let Some(old_version) = old {
            // インターフェースの互換性チェック
            new.verify_interface_compatibility(old_version)?;
            
            // 状態スキーマの互換性チェック
            new.verify_state_compatibility(old_version)?;
        }
        Ok(())
    }
}

// 状態移行の管理
pub struct StateMigration {
    from_version: ModuleVersion,
    to_version: ModuleVersion,
    transforms: Vec<StateTransform>,
}

impl StateMigration {
    pub fn migrate_state(&self, state: State) -> Result<State> {
        let mut current = state;
        for transform in &self.transforms {
            current = transform.apply(current)?;
        }
        Ok(current)
    }
}
```

### リモートデバッグ機能

```rust
// リモートデバッグセッション
pub struct RemoteDebugSession {
    node_id: NodeId,
    connection: DebugConnection,
    event_handler: EventHandler,
}

impl RemoteDebugSession {
    pub async fn attach(&mut self) -> Result<()> {
        self.connection.establish().await?;
        self.sync_breakpoints().await?;
        self.event_handler.start().await?;
        Ok(())
    }
    
    pub async fn fetch_variable(&self, name: &str) -> Result<Value> {
        let request = DebugRequest::FetchVariable { name: name.to_string() };
        self.connection.send_request(request).await
    }
    
    async fn handle_break_event(&self, event: BreakEvent) -> Result<()> {
        let location = event.location();
        let variables = event.variables();
        
        // ブレークポイントでの処理
        println!("Break at {}", location);
        for (name, value) in variables {
            println!("{} = {:?}", name, value);
        }
        
        Ok(())
    }
}

// 分散トレース収集
pub struct DistributedTracer {
    trace_id: TraceId,
    spans: Vec<TraceSpan>,
    remote_traces: HashMap<NodeId, Vec<TraceSpan>>,
}

impl DistributedTracer {
    pub async fn collect_trace(&mut self) -> Result<DistributedTrace> {
        // ローカルトレースの収集
        let local_spans = self.spans.clone();
        
        // リモートトレースの収集
        let mut all_spans = local_spans;
        for spans in self.remote_traces.values() {
            all_spans.extend(spans.clone());
        }
        
        // トレースの整列とマージ
        all_spans.sort_by_key(|span| span.timestamp);
        
        Ok(DistributedTrace {
            id: self.trace_id,
            spans: all_spans,
        })
    }
}
```

### 実装例：ホットリロード対応サービスの実装

```rust
// ホットリロード対応サービス
#[derive(Debug)]
pub struct UserService {
    version: ModuleVersion,
    users: HashMap<UserId, User>,
    state: ServiceState,
}

impl HotReloadable for UserService {
    fn prepare_upgrade(&self) -> Result<ServiceState> {
        // 現在の状態をシリアライズ
        Ok(ServiceState {
            users: self.users.clone(),
            metadata: self.state.metadata.clone(),
        })
    }
    
    fn apply_upgrade(&mut self, new_version: ModuleVersion, state: ServiceState) -> Result<()> {
        self.version = new_version;
        self.state = state;
        
        // 必要に応じて状態を変換
        if self.version.requires_migration() {
            self.migrate_state()?;
        }
        
        Ok(())
    }
}

// サービスの使用例
async fn update_service(
    manager: &mut HotReloadManager,
    service: &mut UserService,
) -> Result<()> {
    let new_module = Module::load("user_service_v2.rs")?;
    manager.reload_module(new_module).await?;
    
    // サービスは自動的に更新される
    println!("Service updated to version: {:?}", service.version);
    Ok(())
}
```

### 今回のまとめ

1. 組込みデバッガーによる強力なデバッグ機能
2. Erlang型のスムーズなホットリロード
3. 分散環境での統合的なデバッグ
4. 実用的なホットリロードサービスの実装

### 次回予告

第5回では、cusinartの運用機能について解説します。障害検知、自動復旧、ノードの動的管理など、実運用に必要な機能の実装について詳しく見ていきます。

### 参考資料
- Erlang Design Principles
- The Art of Debugging
- Distributed Tracing in Practice
- Hot Code Reloading Patterns