Optimize GhCrateMeta::find: Cache url resolution result (#810)

So that we don't have to create multiple HEAD/GET http request to get
the final, redirected url.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2023-02-16 12:51:47 +11:00 committed by GitHub
parent a8b9ae6fda
commit 2e118b3044
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 50 deletions

View file

@ -3,6 +3,8 @@ use std::{path::Path, sync::Arc};
use compact_str::CompactString;
pub use gh_crate_meta::*;
pub use quickinstall::*;
use tokio::sync::OnceCell;
use url::Url;
use crate::{
errors::BinstallError,
@ -60,9 +62,37 @@ pub trait Fetcher: Send + Sync {
/// Data required to fetch a package
#[derive(Clone, Debug)]
pub struct Data {
pub name: CompactString,
pub version: CompactString,
pub repo: Option<String>,
name: CompactString,
version: CompactString,
repo: Option<String>,
repo_final_url: OnceCell<Option<Url>>,
}
impl Data {
pub fn new(name: CompactString, version: CompactString, repo: Option<String>) -> Self {
Self {
name,
version,
repo,
repo_final_url: OnceCell::new(),
}
}
async fn resolve_final_repo_url(&self, client: &Client) -> Result<&Option<Url>, BinstallError> {
self.repo_final_url
.get_or_try_init(move || {
Box::pin(async move {
if let Some(repo) = self.repo.as_deref() {
Ok(Some(
client.get_redirected_final_url(Url::parse(repo)?).await?,
))
} else {
Ok(None)
}
})
})
.await
}
}
/// Target specific data required to fetch a package

View file

@ -92,11 +92,7 @@ impl super::Fetcher for GhCrateMeta {
fn find(self: Arc<Self>) -> AutoAbortJoinHandle<Result<bool, BinstallError>> {
AutoAbortJoinHandle::spawn(async move {
let repo = if let Some(repo) = self.data.repo.as_deref() {
Some(Box::pin(self.client.get_redirected_final_url(Url::parse(repo)?)).await?)
} else {
None
};
let repo = self.data.resolve_final_repo_url(&self.client).await?;
let mut pkg_fmt = self.target_data.meta.pkg_fmt;
@ -156,8 +152,7 @@ impl super::Fetcher for GhCrateMeta {
};
// Convert Option<Url> to Option<String> to reduce size of future.
let repo = repo.map(String::from);
let repo = repo.as_deref().map(|u| u.trim_end_matches('/'));
let repo = repo.as_ref().map(|u| u.as_str().trim_end_matches('/'));
// Use reference to self to fix error of closure
// launch_baseline_find_tasks which moves `this`
@ -337,11 +332,11 @@ mod test {
#[test]
fn defaults() {
let data = Data {
name: "cargo-binstall".to_compact_string(),
version: "1.2.3".to_compact_string(),
repo: Some("https://github.com/ryankurte/cargo-binstall".to_string()),
};
let data = Data::new(
"cargo-binstall".to_compact_string(),
"1.2.3".to_compact_string(),
Some("https://github.com/ryankurte/cargo-binstall".to_string()),
);
let ctx = Context::from_data(&data, "x86_64-unknown-linux-gnu", ".tgz");
assert_eq!(
@ -354,11 +349,11 @@ mod test {
#[should_panic]
fn no_repo() {
let meta = PkgMeta::default();
let data = Data {
name: "cargo-binstall".to_compact_string(),
version: "1.2.3".to_compact_string(),
repo: None,
};
let data = Data::new(
"cargo-binstall".to_compact_string(),
"1.2.3".to_compact_string(),
None,
);
let ctx = Context::from_data(&data, "x86_64-unknown-linux-gnu", ".tgz");
ctx.render_url(meta.pkg_url.as_deref().unwrap()).unwrap();
@ -371,11 +366,11 @@ mod test {
..Default::default()
};
let data = Data {
name: "cargo-binstall".to_compact_string(),
version: "1.2.3".to_compact_string(),
repo: None,
};
let data = Data::new(
"cargo-binstall".to_compact_string(),
"1.2.3".to_compact_string(),
None,
);
let ctx = Context::from_data(&data, "x86_64-unknown-linux-gnu", ".tgz");
assert_eq!(
@ -393,11 +388,11 @@ mod test {
..Default::default()
};
let data = Data {
name: "radio-sx128x".to_compact_string(),
version: "0.14.1-alpha.5".to_compact_string(),
repo: Some("https://github.com/rust-iot/rust-radio-sx128x".to_string()),
};
let data = Data::new(
"radio-sx128x".to_compact_string(),
"0.14.1-alpha.5".to_compact_string(),
Some("https://github.com/rust-iot/rust-radio-sx128x".to_string()),
);
let ctx = Context::from_data(&data, "x86_64-unknown-linux-gnu", ".tgz");
assert_eq!(
@ -413,11 +408,11 @@ mod test {
..Default::default()
};
let data = Data {
name: "radio-sx128x".to_compact_string(),
version: "0.14.1-alpha.5".to_compact_string(),
repo: Some("https://github.com/rust-iot/rust-radio-sx128x".to_string()),
};
let data = Data::new(
"radio-sx128x".to_compact_string(),
"0.14.1-alpha.5".to_compact_string(),
Some("https://github.com/rust-iot/rust-radio-sx128x".to_string()),
);
let ctx = Context::from_data(&data, "x86_64-unknown-linux-gnu", ".tgz");
assert_eq!(
@ -437,11 +432,11 @@ mod test {
..Default::default()
};
let data = Data {
name: "cargo-watch".to_compact_string(),
version: "9.0.0".to_compact_string(),
repo: Some("https://github.com/watchexec/cargo-watch".to_string()),
};
let data = Data::new(
"cargo-watch".to_compact_string(),
"9.0.0".to_compact_string(),
Some("https://github.com/watchexec/cargo-watch".to_string()),
);
let ctx = Context::from_data(&data, "aarch64-apple-darwin", ".txz");
assert_eq!(
@ -458,11 +453,11 @@ mod test {
..Default::default()
};
let data = Data {
name: "cargo-watch".to_compact_string(),
version: "9.0.0".to_compact_string(),
repo: Some("https://github.com/watchexec/cargo-watch".to_string()),
};
let data = Data::new(
"cargo-watch".to_compact_string(),
"9.0.0".to_compact_string(),
Some("https://github.com/watchexec/cargo-watch".to_string()),
);
let ctx = Context::from_data(&data, "aarch64-pc-windows-msvc", ".bin");
assert_eq!(

View file

@ -84,11 +84,11 @@ async fn resolve_inner(
let mut handles: Vec<(Arc<dyn Fetcher>, _)> =
Vec::with_capacity(desired_targets.len() * resolvers.len());
let data = Arc::new(Data {
name: package_info.name.clone(),
version: package_info.version_str.clone(),
repo: package_info.repo.clone(),
});
let data = Arc::new(Data::new(
package_info.name.clone(),
package_info.version_str.clone(),
package_info.repo.clone(),
));
handles.extend(
desired_targets