diff --git a/src/download.rs b/src/download.rs index 15f4324..90e7653 100644 --- a/src/download.rs +++ b/src/download.rs @@ -10,6 +10,8 @@ use reqwest::blocking::Client; use sha2::{Sha256, Digest}; +const MAX_DOWNLOAD_RETRY: u32 = 20; + pub struct DownloadResult { pub hash: omaha::Hash, pub data: File, @@ -57,7 +59,7 @@ pub fn hash_on_disk_sha256(path: &Path, maxlen: Option) -> Result(client: &Client, url: U, path: &Path, print_progress: bool) -> Result +fn do_download_and_hash(client: &Client, url: U, path: &Path, print_progress: bool) -> Result where U: reqwest::IntoUrl + Clone, Url: From, @@ -65,9 +67,9 @@ where let client_url = url.clone(); #[rustfmt::skip] - let mut res = client.get(url) + let mut res = client.get(url.clone()) .send() - .context(format!("client get and send({:?}) failed", client_url.as_str()))?; + .context(format!("client get & send{:?} failed ", client_url.as_str()))?; // Redirect was already handled at this point, so there is no need to touch // response or url again. Simply print info and continue. @@ -98,3 +100,14 @@ where data: file, }) } + +pub fn download_and_hash(client: &Client, url: U, path: &Path, print_progress: bool) -> Result +where + U: reqwest::IntoUrl + Clone, + Url: From, +{ + crate::retry_loop( + || do_download_and_hash(client, url.clone(), path, print_progress), + MAX_DOWNLOAD_RETRY, + ) +} diff --git a/src/lib.rs b/src/lib.rs index 7a73d1c..8b05895 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,4 +3,7 @@ pub use download::DownloadResult; pub use download::download_and_hash; pub use download::hash_on_disk_sha256; +mod util; +pub use util::retry_loop; + pub mod request; diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..9d2327b --- /dev/null +++ b/src/util.rs @@ -0,0 +1,25 @@ +use core::time::Duration; +use std::thread::sleep; + +const RETRY_INTERVAL_MSEC: u64 = 1000; + +pub fn retry_loop(mut func: F, max_tries: u32) -> Result +where + F: FnMut() -> Result, +{ + let mut tries = 0; + + loop { + match func() { + ok @ Ok(_) => return ok, + err @ Err(_) => { + tries += 1; + + if tries >= max_tries { + return err; + } + sleep(Duration::from_millis(RETRY_INTERVAL_MSEC)); + } + } + } +}