1use crate::errors::IsRetryable;
2
3#[derive(Debug, Clone)]
4pub struct RetryConfig {
5 pub retries: usize,
8 pub print_retries: bool,
10}
11
12impl Default for RetryConfig {
13 fn default() -> Self {
14 Self {
15 retries: 2,
16 print_retries: true,
17 }
18 }
19}
20
21pub async fn execute_with_retries<F, Fut, T, E>(config: &RetryConfig, mut execute: F) -> Result<T, E>
25where
26 F: FnMut() -> Fut,
27 Fut: Future<Output = Result<T, E>>,
28 E: IsRetryable + std::fmt::Display,
29{
30 let mut retries_remaining = config.retries;
31 loop {
32 let exec_result = execute().await;
34
35 if retries_remaining > 0
36 && let Err(error) = &exec_result
37 && error.is_retryable()
38 {
39 if config.print_retries {
40 std::eprintln!("Execute got {error}; retrying...");
42 }
43 retries_remaining -= 1;
44 continue;
45 }
46
47 return exec_result;
48 }
49}