parallelize downloadmods resolving

This commit is contained in:
LordMZTE 2021-08-30 22:31:44 +02:00
parent 52d21fba63
commit 86560f8e19

View file

@ -16,11 +16,13 @@ use addonscript::manifest::{
File,
Manifest,
RelationType,
Repository,
RepositoryType,
};
use anyhow::Context;
use async_trait::async_trait;
use crossterm::style::Stylize;
use futures::{stream, StreamExt};
use indicatif::ProgressBar;
use percent_encoding::percent_decode;
use reqwest::Client;
@ -30,7 +32,6 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
use url::Url;
pub async fn run(
@ -52,15 +53,12 @@ pub async fn run(
repos.insert(repo.id.clone(), repo);
}
let mut links = vec![];
let pb = ProgressBar::new(version.relations.len() as u64)
.with_prefix("Resolving")
.with_style(progress_style());
let mut files = vec![];
for rel in version.relations {
pb.inc(1);
// Only mods
if rel.relation_type != RelationType::Mod {
pb.println(
@ -85,62 +83,20 @@ pub async fn run(
continue;
}
let rels = match file {
File::Link {
link, installer, ..
} => (installer, link),
File::Maven {
installer,
artifact,
repository,
} => {
let repo = repos.get(&repository).with_context(|| {
format!("File references non-existant repository `{}`", repository)
})?;
let url = match repo.repo_type {
RepositoryType::Maven => {
let url = mvn_artifact_to_url(&artifact, &repo)?;
pb.println(format!(
"{} {}",
"Resolved maven artifact with url".green(),
url.as_str().cyan().bold()
));
url
},
RepositoryType::Curseforge => {
let mut splits = artifact.split(':').skip(1);
let p_id = splits
.next()
.context("Couldn't parse curseforge artifact!")?;
let f_id = splits
.next()
.context("Couldn't parse curseforge artifact!")?;
let url = format!(
"https://addons-ecs.forgesvc.net/api/v2/addon/{}/file/{}/download-url",
p_id, f_id
);
let url = Url::parse(http.get(url).send().await?.text().await?.trim())
.context("failed to parse curseforge URL")?;
pb.println(format!(
"{} {}",
"Resolved curseforge artifact with url".green(),
url.as_str().cyan().bold()
));
url
},
};
(installer, Link::Http(url))
},
};
links.push(rels);
files.push(file);
}
let http_ = Arc::clone(&http);
let mut futures = stream::iter(files.into_iter())
.map(|f| process_file(f, &repos, &pb, Arc::clone(&http_)))
.buffer_unordered(config.downloads.max_threads);
let mut links = vec![];
while let Some(x) = futures.next().await {
pb.inc(1);
links.push(x?);
}
pb.finish();
let mut files = vec![];
@ -233,3 +189,64 @@ pub async fn run(
Ok(())
}
async fn process_file(
file: File,
repos: &HashMap<String, Repository>,
pb: &ProgressBar,
http: Arc<Client>,
) -> anyhow::Result<(Installer, Link)> {
Ok(match file {
File::Link {
link, installer, ..
} => (installer, link),
File::Maven {
installer,
artifact,
repository,
} => {
let repo = repos.get(&repository).with_context(|| {
format!("File references non-existant repository `{}`", repository)
})?;
let url = match repo.repo_type {
RepositoryType::Maven => {
let url = mvn_artifact_to_url(&artifact, &repo)?;
pb.println(format!(
"{} {}",
"Resolved maven artifact with url".green(),
url.as_str().cyan().bold()
));
url
},
RepositoryType::Curseforge => {
let mut splits = artifact.split(':').skip(1);
let p_id = splits
.next()
.context("Couldn't parse curseforge artifact!")?;
let f_id = splits
.next()
.context("Couldn't parse curseforge artifact!")?;
let url = format!(
"https://addons-ecs.forgesvc.net/api/v2/addon/{}/file/{}/download-url",
p_id, f_id
);
let url = Url::parse(http.get(url).send().await?.text().await?.trim())
.context("failed to parse curseforge URL")?;
pb.println(format!(
"{} {}",
"Resolved curseforge artifact with url".green(),
url.as_str().cyan().bold()
));
url
},
};
(installer, Link::Http(url))
},
})
}