Skip to main content

aria2_core/engine/
command.rs

1use crate::error::Result;
2use async_trait::async_trait;
3use std::time::{Duration, Instant};
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum CommandStatus {
7    Pending,
8    Running,
9    Completed,
10}
11
12/// Progress update sent from a download command to the engine via channel.
13/// This decouples the download task from the RequestGroup RwLock: instead of
14/// acquiring `group.write().await` on every batched progress checkpoint, the
15/// download task performs a cheap lock-free `send` and a single aggregator
16/// task applies the update to the `RequestGroup`.
17///
18/// Fields:
19/// - `completed_bytes`: total bytes downloaded so far for this command.
20/// - `download_speed`: current download speed in bytes/sec. `0` means the
21///   sender did not refresh the speed sample this tick (the aggregator keeps
22///   the previously cached value).
23/// - `upload_speed`: upload speed in bytes/sec (BT only; `0` for HTTP/FTP).
24#[derive(Debug, Clone)]
25pub struct ProgressUpdate {
26    /// Total bytes downloaded so far for this command.
27    pub completed_bytes: u64,
28    /// Current download speed in bytes/sec (0 if not yet calculated).
29    pub download_speed: u64,
30    /// Upload speed in bytes/sec (for BT, 0 for HTTP).
31    pub upload_speed: u64,
32}
33
34#[async_trait]
35pub trait Command: Send + Sync {
36    async fn execute(&mut self) -> Result<()>;
37
38    fn status(&self) -> CommandStatus;
39
40    fn timeout(&self) -> Option<Duration> {
41        None
42    }
43
44    /// Returns the instant at which this command started executing, if the
45    /// engine has informed the command via [`set_started_at`].
46    ///
47    /// The default implementation reports `None`; commands that wish to
48    /// self-report elapsed time (e.g. for `status()` queries) may override
49    /// this together with [`set_started_at`].
50    fn started_at(&self) -> Option<Instant> {
51        None
52    }
53
54    /// Called by the engine immediately before the command is spawned onto a
55    /// background task. The default implementation is a no-op; commands that
56    /// store the instant can expose it through [`started_at`].
57    fn set_started_at(&mut self, _instant: Instant) {}
58}