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