avail_rust_client/clients/
utils.rs

1use 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}