avail_rust_client/clients/
utils.rs1use crate::platform::sleep;
2use std::{fmt::Debug, time::Duration};
3
4#[cfg(feature = "tracing")]
5pub(crate) fn trace_warn(message: &str) {
6 tracing::warn!(target: "lib", message);
7}
8
9pub async fn with_retry_on_error<F, Fut, O, E>(f: F, retry_on_error: bool) -> Result<O, E>
10where
11 F: Fn() -> Fut,
12 Fut: Future<Output = Result<O, E>>,
13 E: Debug,
14{
15 let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
16 if !retry_on_error {
17 sleep_duration.clear();
18 }
19
20 loop {
21 match f().await {
22 Ok(x) => return Ok(x),
23 Err(err) => {
24 let Some(duration) = sleep_duration.pop() else {
25 return Err(err);
26 };
27
28 #[cfg(feature = "tracing")]
29 trace_warn(&std::format!("Retrying after error: {:?}; next attempt in {}s", err, duration));
30 sleep(Duration::from_secs(duration)).await;
31 },
32 };
33 }
34}
35
36pub async fn with_retry_on_error_and_none<F, Fut, O, E>(
37 f: F,
38 retry_on_error: bool,
39 retry_on_none: bool,
40) -> Result<Option<O>, E>
41where
42 F: Fn() -> Fut,
43 Fut: Future<Output = Result<Option<O>, E>>,
44 E: Debug,
45{
46 let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
47 loop {
48 match f().await {
49 Ok(Some(x)) => return Ok(Some(x)),
50 Ok(None) if !retry_on_none => {
51 return Ok(None);
52 },
53 Ok(None) => {
54 let Some(duration) = sleep_duration.pop() else {
55 return Ok(None);
56 };
57
58 #[cfg(feature = "tracing")]
59 trace_warn(&std::format!(
60 "Received None result; retrying in {}s because retry_on_none is enabled",
61 duration
62 ));
63 sleep(Duration::from_secs(duration)).await;
64 },
65 Err(err) if !retry_on_error => {
66 return Err(err);
67 },
68 Err(err) => {
69 let Some(duration) = sleep_duration.pop() else {
70 return Err(err);
71 };
72
73 #[cfg(feature = "tracing")]
74 trace_warn(&std::format!(
75 "Retrying after error while awaiting Option result: {:?}; next attempt in {}s",
76 err,
77 duration
78 ));
79 sleep(Duration::from_secs(duration)).await;
80 },
81 };
82 }
83}