pacenotes_installer\worker/
download_run.rs1const REPORT_EVERY: std::time::Duration = std::time::Duration::from_millis(100);
4
5pub struct DownloadJob {
8 pub base_url: String,
9 pub token: Option<String>,
10 pub cache_root: std::path::PathBuf,
11 pub downloads: Vec<pacenotes_shared::PackageInfo>,
14 pub cancel: std::sync::Arc<std::sync::atomic::AtomicBool>,
15}
16
17pub fn run_download(job: DownloadJob, reporter: &super::Reporter) -> super::Message {
23 let api = crate::api::Api::new(&job.base_url, job.token.clone());
24 let mut cache = pacenotes_installer::cache::Cache::open(&job.cache_root);
25 let missing = &job.downloads;
26 let total: u64 = missing.iter().map(|package| package.size).sum();
27 let mut done: u64 = 0;
28 let mut downloaded = 0;
29 let mut bytes: u64 = 0;
30 let mut failed = Vec::new();
31
32 for package in missing {
33 let report = |item_done: u64, log: Option<String>| {
34 reporter.send(super::Progress {
35 phase: super::Phase::Download,
36 item: package.label().to_string(),
37 item_done,
38 item_size: package.size,
39 done: done + item_done,
40 total,
41 log,
42 });
43 };
44 report(
45 0,
46 Some(format!(
47 "downloading {} ({})",
48 package.download_path(),
49 pacenotes_installer::size::human(package.size)
50 )),
51 );
52
53 let mut last_post = std::time::Instant::now();
54 let mut progress = |read: u64, _content_length: Option<u64>| {
55 if last_post.elapsed() >= REPORT_EVERY {
56 last_post = std::time::Instant::now();
57 report(read, None);
58 }
59 };
60 let mut on_retry = |error: &crate::http::HttpError, delay_ms: u64| {
61 let line = format!(
62 "retrying {} in {} s: {}",
63 package.download_path(),
64 delay_ms / 1000,
65 error.message
66 );
67 report(0, Some(line));
68 };
69 match crate::package_download::download_retrying(
70 &api,
71 package,
72 &mut cache,
73 &mut progress,
74 &job.cancel,
75 &mut on_retry,
76 ) {
77 Ok(()) => {
78 downloaded += 1;
79 bytes += package.size;
80 }
81 Err(e) if e.is_cancelled() => {
82 return super::Message::Downloaded(super::Fetched::Cancelled)
83 }
84 Err(e) => failed.push(super::NotDownloaded {
85 key: package.download_path(),
86 label: package.label().to_string(),
87 reason: e.message,
88 }),
89 }
90 done += package.size;
92 }
93
94 super::Message::Downloaded(super::Fetched::Done {
95 downloaded,
96 bytes,
97 failed,
98 })
99}