Skip to content

Commit 13d7529

Browse files
committed
ref: retry_with_total_timeout
1 parent b620c3b commit 13d7529

File tree

1 file changed

+25
-24
lines changed

1 file changed

+25
-24
lines changed

src/robust_provider.rs

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{future::Future, sync::Arc, time::Duration};
1+
use std::{fmt::Debug, future::Future, sync::Arc, time::Duration};
22

33
use alloy::{
44
eips::{BlockId, BlockNumberOrTag},
@@ -230,44 +230,45 @@ impl<N: Network> RobustProvider<N> {
230230
/// and all fallback providers failed" if the overall timeout elapses and no fallback
231231
/// providers succeed.
232232
/// - Propagates any [`RpcError<TransportErrorKind>`] from the underlying retries.
233-
async fn retry_with_total_timeout<T, F, Fut>(&self, operation: F) -> Result<T, Error>
233+
async fn retry_with_total_timeout<T: Debug, F, Fut>(&self, operation: F) -> Result<T, Error>
234234
where
235235
F: Fn(RootProvider<N>) -> Fut,
236236
Fut: Future<Output = Result<T, RpcError<TransportErrorKind>>>,
237237
{
238-
let mut last_error = None;
239-
240-
// Try each provider in sequence (first one is primary)
241-
for (idx, provider) in self.providers.iter().enumerate() {
242-
if idx == 0 {
243-
info!("Attempting primary provider");
244-
} else {
245-
info!("Attempting fallback provider {} out of {}", idx, self.providers.len() - 1);
246-
}
238+
let mut providers = self.providers.iter();
239+
let primary = providers.next().expect("should have primary provider");
240+
241+
let result = self.try_provider_with_timeout(primary, &operation).await;
242+
243+
if result.is_ok() {
244+
return result;
245+
}
246+
247+
let mut last_error = result.unwrap_err();
248+
249+
if self.providers.len() > 1 {
250+
info!("Primary provider failed, trying fallback provider(s)");
251+
}
247252

248-
let result = self.try_provider_with_timeout(provider, &operation).await;
253+
// This loop starts at index 1 automatically
254+
for (idx, provider) in providers.enumerate() {
255+
let fallback_num = idx + 1;
256+
info!("Attempting fallback provider {}/{}", fallback_num, self.providers.len() - 1);
249257

250-
match result {
258+
match self.try_provider_with_timeout(provider, &operation).await {
251259
Ok(value) => {
252-
if idx > 0 {
253-
info!(provider_num = idx, "Fallback provider succeeded");
254-
}
260+
info!(provider_num = fallback_num, "Fallback provider succeeded");
255261
return Ok(value);
256262
}
257263
Err(e) => {
258-
last_error = Some(e);
259-
if idx == 0 && self.providers.len() > 1 {
260-
info!("Primary provider failed, trying fallback provider(s)");
261-
} else {
262-
error!(provider_num = idx, err = %last_error.as_ref().unwrap(), "Fallback provider failed with error");
263-
}
264+
error!(provider_num = fallback_num, err = %e, "Fallback provider failed");
265+
last_error = e;
264266
}
265267
}
266268
}
267269

268270
error!("All providers failed or timed out");
269-
// Return the last error encountered
270-
Err(last_error.unwrap_or(Error::Timeout))
271+
Err(last_error)
271272
}
272273

273274
/// Try executing an operation with a specific provider with retry and timeout.

0 commit comments

Comments
 (0)