gglib_core/ports/download_state.rs
1//! Download state repository port definition.
2//!
3//! This port defines the interface for persisting download queue state.
4//! Implementations handle durable storage of queued downloads so they
5//! survive application restarts.
6//!
7//! # Design
8//!
9//! - Persists queue state and terminal results only
10//! - Fine-grained progress stays in-memory (high churn, not worth persisting)
11//! - Intent-based methods, not generic CRUD
12
13use async_trait::async_trait;
14
15use super::RepositoryError;
16use crate::download::{DownloadId, DownloadStatus, QueuedDownload};
17
18/// Port for persisting download queue state.
19///
20/// This trait is implemented by `gglib-db` and injected into the download
21/// manager to provide durable queue storage.
22///
23/// # Persistence Scope
24///
25/// **Persisted:**
26/// - Queued downloads (survive restarts)
27/// - Terminal results (completed/failed with enough info for history)
28/// - Retry counts (if retries are supported)
29///
30/// **In-memory only:**
31/// - Fine-grained progress (bytes, speed)
32/// - Active progress snapshots (broadcast via events)
33///
34/// # Usage
35///
36/// ```ignore
37/// let repo: Arc<dyn DownloadStateRepositoryPort> = /* ... */;
38/// repo.enqueue(&queued_download).await?;
39/// let queue = repo.load_queue().await?;
40/// ```
41#[async_trait]
42pub trait DownloadStateRepositoryPort: Send + Sync {
43 /// Add a download to the persistent queue.
44 ///
45 /// The download should be in `Queued` status when enqueued.
46 async fn enqueue(&self, download: &QueuedDownload) -> Result<(), RepositoryError>;
47
48 /// Update the status of an existing download.
49 ///
50 /// This is used to transition downloads through their lifecycle:
51 /// Queued -> Downloading -> Completed/Failed/Cancelled
52 async fn update_status(
53 &self,
54 id: &DownloadId,
55 status: DownloadStatus,
56 ) -> Result<(), RepositoryError>;
57
58 /// Load all queued downloads from persistent storage.
59 ///
60 /// Returns downloads that were queued but not yet completed.
61 /// Used on application startup to restore the queue.
62 async fn load_queue(&self) -> Result<Vec<QueuedDownload>, RepositoryError>;
63
64 /// Mark a download as failed with an error message.
65 ///
66 /// This records the failure for history/retry purposes.
67 async fn mark_failed(
68 &self,
69 id: &DownloadId,
70 error_message: &str,
71 ) -> Result<(), RepositoryError>;
72
73 /// Remove a download from the persistent queue.
74 ///
75 /// Used when a download is cancelled or cleaned up.
76 async fn remove(&self, id: &DownloadId) -> Result<(), RepositoryError>;
77
78 /// Prune completed/failed downloads older than the given age.
79 ///
80 /// This is optional cleanup to prevent unbounded growth.
81 async fn prune_completed(&self, older_than_days: u32) -> Result<u32, RepositoryError>;
82}