kithara_stream/dl/config.rs
1use bon::Builder;
2use kithara_abr::AbrSettings;
3use kithara_net::HttpClient;
4use kithara_platform::{time::Duration, tokio::runtime::Handle};
5use tokio_util::sync::CancellationToken;
6
7/// Configuration for [`Downloader`](super::Downloader).
8#[derive(Clone, Builder)]
9#[non_exhaustive]
10pub struct DownloaderConfig {
11 /// Settings for the shared ABR controller owned by the Downloader.
12 #[builder(default)]
13 pub abr_settings: AbrSettings,
14 /// Cancellation token — when cancelled, the download loop exits.
15 #[builder(default = CancellationToken::new())] // kithara:cancel:owner
16 pub cancel: CancellationToken,
17 /// Throttle delay for demand (low-priority) processing.
18 /// Gives urgent work a chance to preempt before demand batch runs.
19 #[builder(default = Duration::ZERO)]
20 pub demand_throttle: Duration,
21 /// Soft timeout. When a fetch has not produced a response within
22 /// this duration, the Downloader publishes
23 /// [`DownloaderEvent::LoadSlow`](kithara_events::DownloaderEvent::LoadSlow)
24 /// on the peer's bus (if any). The request itself is not aborted
25 /// — it keeps running until hard timeout fires.
26 #[builder(default = Duration::from_secs(2))]
27 pub soft_timeout: Duration,
28 /// HTTP client used for all fetches. Cloned by the Downloader to
29 /// share the underlying `reqwest::Client` (and its connection pool)
30 /// with the caller. Pass a single shared `HttpClient` to multiple
31 /// Downloaders to share keep-alive sockets across them.
32 pub client: HttpClient,
33 /// Tokio runtime handle for the download loop.
34 ///
35 /// - `Some(handle)` — the loop runs as a task on this runtime.
36 /// - `None` — spawns as a task on the current runtime via `task::spawn`.
37 pub runtime: Option<Handle>,
38 /// Maximum number of concurrent in-flight fetch commands.
39 #[builder(default = 5)]
40 pub max_concurrent: usize,
41}
42
43impl DownloaderConfig {
44 /// Start a builder with `client` already set. Mirrors the
45 /// `ResourceConfig::for_src` / `HlsConfig::for_url` pattern — the
46 /// one required field is pre-supplied so callers can chain only
47 /// the optional knobs they care about.
48 pub fn for_client(
49 client: HttpClient,
50 ) -> DownloaderConfigBuilder<downloader_config_builder::SetClient> {
51 Self::builder().client(client)
52 }
53}