vtcode_core/diagnostics/
recovery.rs1use std::sync::Arc;
2
3use anyhow::Result;
4use async_trait::async_trait;
5
6#[async_trait]
8pub trait RecoveryAction: Send + Sync {
9 async fn execute(&self) -> Result<()>;
10 fn name(&self) -> &'static str;
11}
12
13#[derive(Default, Clone)]
15pub struct RecoveryPlaybook {
16 actions: Vec<Arc<dyn RecoveryAction>>,
17}
18
19impl RecoveryPlaybook {
20 pub fn new(actions: Vec<Arc<dyn RecoveryAction>>) -> Self {
21 Self { actions }
22 }
23
24 pub fn with_action(mut self, action: Arc<dyn RecoveryAction>) -> Self {
25 self.actions.push(action);
26 self
27 }
28
29 pub async fn execute_all(&self) -> Result<Vec<String>> {
30 let mut results = Vec::new();
31 for action in &self.actions {
32 action.execute().await?;
33 results.push(action.name().to_string());
34 }
35 Ok(results)
36 }
37}
38
39pub struct LabeledAction {
41 label: &'static str,
42}
43
44impl LabeledAction {
45 pub fn new(label: &'static str) -> Self {
46 Self { label }
47 }
48}
49
50#[async_trait]
51impl RecoveryAction for LabeledAction {
52 async fn execute(&self) -> Result<()> {
53 Ok(())
54 }
55
56 fn name(&self) -> &'static str {
57 self.label
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[tokio::test]
66 async fn executes_all_actions() {
67 let playbook =
68 RecoveryPlaybook::default().with_action(Arc::new(LabeledAction::new("reset")));
69 let executed = playbook.execute_all().await.expect("playbook should run");
70 assert_eq!(executed, vec!["reset".to_string()]);
71 }
72}