From c393270899f90eb2862d2293fc577f09bc0feb7c Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 15:29:09 +1000 Subject: [PATCH] Run fetchers in parallel in `MultiFetcher.first_available` Signed-off-by: Jiahao XU --- src/fetchers.rs | 56 ++++++++++++++++++++++++++++++++++++++----------- src/main.rs | 2 +- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/fetchers.rs b/src/fetchers.rs index 08b43d1e..a7384985 100644 --- a/src/fetchers.rs +++ b/src/fetchers.rs @@ -4,6 +4,7 @@ use std::sync::Arc; pub use gh_crate_meta::*; pub use log::debug; pub use quickinstall::*; +use tokio::task::JoinHandle; use crate::{BinstallError, PkgFmt, PkgMeta}; @@ -53,22 +54,53 @@ impl MultiFetcher { self.fetchers.push(fetcher); } - pub async fn first_available(&self) -> Option<&dyn Fetcher> { - for fetcher in &self.fetchers { - let available = fetcher.check().await.unwrap_or_else(|err| { - debug!( - "Error while checking fetcher {}: {}", - fetcher.source_name(), - err - ); - false - }); + pub async fn first_available(&self) -> Option> { + let handles: Vec<_> = self + .fetchers + .iter() + .cloned() + .map(|fetcher| { + let fetcher_cloned = fetcher.clone(); - if available { - return Some(&**fetcher); + ( + AutoAbortJoinHandle(tokio::spawn(async move { + fetcher.check().await.unwrap_or_else(|err| { + debug!( + "Error while checking fetcher {}: {}", + fetcher.source_name(), + err + ); + false + }) + })), + fetcher_cloned, + ) + }) + .collect(); + + for (mut handle, fetcher) in handles { + match (&mut handle.0).await { + Ok(true) => return Some(fetcher), + Err(join_err) => { + debug!( + "Error while checking fetcher {}: {}", + fetcher.source_name(), + join_err + ); + } + _ => (), } } None } } + +#[derive(Debug)] +struct AutoAbortJoinHandle(JoinHandle); + +impl Drop for AutoAbortJoinHandle { + fn drop(&mut self) { + self.0.abort(); + } +} diff --git a/src/main.rs b/src/main.rs index a9479a2d..5c913dc5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -234,7 +234,7 @@ async fn entry() -> Result<()> { Some(fetcher) => { install_from_package( binaries, - fetcher, + &*fetcher, install_path, meta, opts,