Add download lifecycle controls
This commit is contained in:
@@ -49,6 +49,52 @@ impl DownloadEntry {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pause(&mut self) -> Result<(), DomainError> {
|
||||
self.require_state("pause", &[DownloadState::InProgress])?;
|
||||
self.state = DownloadState::Paused;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn resume(&mut self) -> Result<(), DomainError> {
|
||||
self.require_state("resume", &[DownloadState::Paused])?;
|
||||
self.state = DownloadState::InProgress;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn cancel(&mut self) -> Result<(), DomainError> {
|
||||
self.require_state("cancel", &[DownloadState::InProgress, DownloadState::Paused])?;
|
||||
self.state = DownloadState::Cancelled;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn retry(&mut self) -> Result<(), DomainError> {
|
||||
self.require_state("retry", &[DownloadState::Cancelled, DownloadState::Failed])?;
|
||||
self.state = DownloadState::InProgress;
|
||||
self.received_bytes = 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_progress(&mut self, received_bytes: u64) -> Result<(), DomainError> {
|
||||
self.require_state("update progress", &[DownloadState::InProgress])?;
|
||||
self.validate_received_bytes(received_bytes)?;
|
||||
self.received_bytes = received_bytes;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn complete(&mut self, received_bytes: u64) -> Result<(), DomainError> {
|
||||
self.require_state("complete", &[DownloadState::InProgress])?;
|
||||
self.validate_received_bytes(received_bytes)?;
|
||||
self.received_bytes = received_bytes;
|
||||
self.state = DownloadState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fail(&mut self) -> Result<(), DomainError> {
|
||||
self.require_state("fail", &[DownloadState::InProgress, DownloadState::Paused])?;
|
||||
self.state = DownloadState::Failed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn id(&self) -> &DownloadId {
|
||||
&self.id
|
||||
@@ -88,4 +134,39 @@ impl DownloadEntry {
|
||||
pub fn started_at(&self) -> SystemTime {
|
||||
self.started_at
|
||||
}
|
||||
|
||||
fn require_state(
|
||||
&self,
|
||||
action: &'static str,
|
||||
allowed_states: &[DownloadState],
|
||||
) -> Result<(), DomainError> {
|
||||
if allowed_states.iter().any(|state| state == &self.state) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(DomainError::InvalidDownloadTransition { action, state: self.state.as_str() })
|
||||
}
|
||||
|
||||
fn validate_received_bytes(&self, received_bytes: u64) -> Result<(), DomainError> {
|
||||
if let Some(total_bytes) = self.total_bytes
|
||||
&& received_bytes > total_bytes
|
||||
{
|
||||
return Err(DomainError::InvalidDownloadProgress { received_bytes, total_bytes });
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl DownloadState {
|
||||
#[must_use]
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::InProgress => "in_progress",
|
||||
Self::Paused => "paused",
|
||||
Self::Completed => "completed",
|
||||
Self::Cancelled => "cancelled",
|
||||
Self::Failed => "failed",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,4 +10,10 @@ pub enum DomainError {
|
||||
|
||||
#[error("invalid command query")]
|
||||
InvalidCommand,
|
||||
|
||||
#[error("cannot {action} download while state is {state}")]
|
||||
InvalidDownloadTransition { action: &'static str, state: &'static str },
|
||||
|
||||
#[error("download progress {received_bytes} exceeds total {total_bytes}")]
|
||||
InvalidDownloadProgress { received_bytes: u64, total_bytes: u64 },
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user