reth_cli_commands/download/
session.rs1use super::progress::{DownloadRequestLimiter, SharedProgress};
2use eyre::Result;
3use reth_cli_util::cancellation::CancellationToken;
4use std::{
5 path::{Path, PathBuf},
6 sync::Arc,
7 time::Duration,
8};
9
10#[derive(Clone)]
12pub(crate) struct DownloadSession {
13 progress: Option<Arc<SharedProgress>>,
15 request_limiter: Option<Arc<DownloadRequestLimiter>>,
17 cancel_token: CancellationToken,
19 retry_backoff: Option<Duration>,
21}
22
23impl DownloadSession {
24 pub(crate) fn new(
26 progress: Option<Arc<SharedProgress>>,
27 request_limiter: Option<Arc<DownloadRequestLimiter>>,
28 cancel_token: CancellationToken,
29 ) -> Self {
30 Self { progress, request_limiter, cancel_token, retry_backoff: None }
31 }
32
33 pub(crate) const fn with_retry_backoff(mut self, retry_backoff: Option<Duration>) -> Self {
35 self.retry_backoff = retry_backoff;
36 self
37 }
38
39 pub(crate) fn retry_delay(&self, default: Duration) -> Duration {
41 self.retry_backoff.unwrap_or(default)
42 }
43
44 pub(crate) fn progress(&self) -> Option<&Arc<SharedProgress>> {
46 self.progress.as_ref()
47 }
48
49 pub(crate) fn request_limiter(&self) -> Option<&Arc<DownloadRequestLimiter>> {
51 self.request_limiter.as_ref()
52 }
53
54 pub(crate) fn require_request_limiter(&self) -> Result<&Arc<DownloadRequestLimiter>> {
56 self.request_limiter().ok_or_else(|| eyre::eyre!("Missing download request limiter"))
57 }
58
59 pub(crate) fn cancel_token(&self) -> &CancellationToken {
61 &self.cancel_token
62 }
63
64 pub(crate) fn record_reused_archive(&self, download_bytes: u64, output_bytes: u64) {
66 if let Some(progress) = self.progress() {
67 progress.record_reused_archive(download_bytes, output_bytes);
68 }
69 }
70
71 pub(crate) fn record_archive_output_complete(&self, bytes: u64) {
73 if let Some(progress) = self.progress() {
74 progress.record_archive_output_complete(bytes);
75 }
76 }
77}
78
79#[derive(Clone)]
81pub(crate) struct ArchiveProcessContext {
82 target_dir: PathBuf,
84 cache_dir: Option<PathBuf>,
86 session: DownloadSession,
88}
89
90impl ArchiveProcessContext {
91 pub(crate) fn new(
93 target_dir: PathBuf,
94 cache_dir: Option<PathBuf>,
95 session: DownloadSession,
96 ) -> Self {
97 Self { target_dir, cache_dir, session }
98 }
99
100 pub(crate) fn target_dir(&self) -> &Path {
102 &self.target_dir
103 }
104
105 pub(crate) fn cache_dir(&self) -> Option<&Path> {
107 self.cache_dir.as_deref()
108 }
109
110 pub(crate) fn session(&self) -> &DownloadSession {
112 &self.session
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn retry_delay_preserves_defaults_or_uses_override() {
122 let session = DownloadSession::new(None, None, CancellationToken::new());
123 for default in [Duration::from_secs(2), Duration::from_secs(5), Duration::from_secs(40)] {
124 assert_eq!(session.retry_delay(default), default);
125 for delay in [Duration::ZERO, Duration::from_millis(250)] {
126 assert_eq!(
127 session.clone().with_retry_backoff(Some(delay)).retry_delay(default),
128 delay
129 );
130 }
131 }
132 }
133}