mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
7c3c13cecf
Fixes #26085. Adds a basic retry utility with some defaults, starts off with a 100ms wait, then 250ms, then 500ms I've applied the retry in the http client, reusing an existing function, so this also applies to retrying downloads of deno binaries in `upgrade` and `compile`. I can make a separate function that doesn't retry so this doesn't affect `upgrade` and `compile`, but it seemed desirable to have retries there too, so I left it in.
41 lines
944 B
Rust
41 lines
944 B
Rust
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
|
|
use std::future::Future;
|
|
use std::time::Duration;
|
|
|
|
pub fn retry<
|
|
F: FnMut() -> Fut,
|
|
T,
|
|
E,
|
|
Fut: Future<Output = Result<T, E>>,
|
|
ShouldRetry: FnMut(&E) -> bool,
|
|
>(
|
|
mut f: F,
|
|
mut should_retry: ShouldRetry,
|
|
) -> impl Future<Output = Result<T, E>> {
|
|
const WAITS: [Duration; 3] = [
|
|
Duration::from_millis(100),
|
|
Duration::from_millis(250),
|
|
Duration::from_millis(500),
|
|
];
|
|
|
|
let mut waits = WAITS.into_iter();
|
|
async move {
|
|
let mut first_result = None;
|
|
loop {
|
|
let result = f().await;
|
|
match result {
|
|
Ok(r) => return Ok(r),
|
|
Err(e) if !should_retry(&e) => return Err(e),
|
|
_ => {}
|
|
}
|
|
if first_result.is_none() {
|
|
first_result = Some(result);
|
|
}
|
|
let Some(wait) = waits.next() else {
|
|
return first_result.unwrap();
|
|
};
|
|
tokio::time::sleep(wait).await;
|
|
}
|
|
}
|
|
}
|