doum_cli/llm/
retry.rs

1use anyhow::Result;
2use std::future::Future;
3
4/// Retry LLM call with parsing when either the call or parsing fails
5pub async fn retry_with_parse<T, F, Fut, P>(llm_call: F, parser: P, max_retries: u32) -> Result<T>
6where
7    F: Fn() -> Fut,
8    Fut: Future<Output = Result<String>>,
9    P: Fn(&str) -> Result<T>,
10{
11    let mut last_error = None;
12
13    for attempt in 1..=max_retries {
14        // Call LLM
15        let response = match llm_call().await {
16            Ok(resp) => resp,
17            Err(e) => {
18                last_error = Some(e);
19                if attempt < max_retries {
20                    tracing::warn!(
21                        "LLM call failed (attempt {}/{}): Retrying...",
22                        attempt,
23                        max_retries
24                    );
25                    continue;
26                } else {
27                    tracing::error!("All retry attempts exhausted.");
28                    break;
29                }
30            }
31        };
32
33        // Parse response
34        match parser(&response) {
35            Ok(parsed) => return Ok(parsed),
36            Err(e) => {
37                last_error = Some(e);
38                if attempt < max_retries {
39                    tracing::warn!(
40                        "Parse failed (attempt {}/{}): Retrying...",
41                        attempt,
42                        max_retries
43                    );
44                    continue;
45                } else {
46                    tracing::error!("All retry attempts exhausted.");
47                    break;
48                }
49            }
50        }
51    }
52
53    // All retries exhausted
54    Err(last_error.unwrap_or_else(|| anyhow::anyhow!("Unknown error after retries")))
55}