subx_cli/services/ai/
retry.rs1use crate::Result;
2use tokio::time::{Duration, sleep};
3
4pub struct RetryConfig {
6 pub max_attempts: usize,
7 pub base_delay: Duration,
8 pub max_delay: Duration,
9 pub backoff_multiplier: f64,
10}
11
12impl Default for RetryConfig {
13 fn default() -> Self {
14 Self {
15 max_attempts: 3,
16 base_delay: Duration::from_millis(1000),
17 max_delay: Duration::from_secs(30),
18 backoff_multiplier: 2.0,
19 }
20 }
21}
22
23pub async fn retry_with_backoff<F, Fut, T>(operation: F, config: &RetryConfig) -> Result<T>
25where
26 F: Fn() -> Fut,
27 Fut: std::future::Future<Output = Result<T>>,
28{
29 let mut last_error = None;
30
31 for attempt in 0..config.max_attempts {
32 match operation().await {
33 Ok(result) => return Ok(result),
34 Err(e) => {
35 last_error = Some(e);
36
37 if attempt < config.max_attempts - 1 {
38 let delay = std::cmp::min(
39 Duration::from_millis(
40 (config.base_delay.as_millis() as f64
41 * config.backoff_multiplier.powi(attempt as i32))
42 as u64,
43 ),
44 config.max_delay,
45 );
46 sleep(delay).await;
47 }
48 }
49 }
50 }
51
52 Err(last_error.unwrap())
53}