avail_rust_client/
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>
38where
39 F: Fn() -> Fut,
40 Fut: Future<Output = Result<O, E>>,
41 E: Debug,
42{
43 let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
44 if !retry_on_error {
45 sleep_duration.clear();
46 }
47
48 loop {
49 match f().await {
50 Ok(x) => return Ok(x),
51 Err(err) => {
52 let Some(duration) = sleep_duration.pop() else {
53 return Err(err);
54 };
55
56 #[cfg(feature = "tracing")]
57 trace_warn(&std::format!("Retrying after error: {:?}; next attempt in {}s", err, duration));
58 sleep(Duration::from_secs(duration)).await;
59 },
60 };
61 }
62}
63
64pub async fn with_retry_on_error_and_none<F, Fut, O, E>(
94 f: F,
95 retry_on_error: bool,
96 retry_on_none: bool,
97) -> Result<Option<O>, E>
98where
99 F: Fn() -> Fut,
100 Fut: Future<Output = Result<Option<O>, E>>,
101 E: Debug,
102{
103 let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
104 loop {
105 match f().await {
106 Ok(Some(x)) => return Ok(Some(x)),
107 Ok(None) if !retry_on_none => {
108 return Ok(None);
109 },
110 Ok(None) => {
111 let Some(duration) = sleep_duration.pop() else {
112 return Ok(None);
113 };
114
115 #[cfg(feature = "tracing")]
116 trace_warn(&std::format!(
117 "Received None result; retrying in {}s because retry_on_none is enabled",
118 duration
119 ));
120 sleep(Duration::from_secs(duration)).await;
121 },
122 Err(err) if !retry_on_error => {
123 return Err(err);
124 },
125 Err(err) => {
126 let Some(duration) = sleep_duration.pop() else {
127 return Err(err);
128 };
129
130 #[cfg(feature = "tracing")]
131 trace_warn(&std::format!(
132 "Retrying after error while awaiting Option result: {:?}; next attempt in {}s",
133 err,
134 duration
135 ));
136 sleep(Duration::from_secs(duration)).await;
137 },
138 };
139 }
140}