Fix download manager (#7933)
Co-authored-by: Douwe Osinga <douwe@squareup.com> Co-authored-by: jh-block <jhugo@block.xyz> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,9 @@ pub struct DownloadProgress {
|
||||
pub eta_seconds: Option<u64>,
|
||||
/// Error message if failed
|
||||
pub error: Option<String>,
|
||||
/// Whether the background download task has exited
|
||||
#[serde(skip)]
|
||||
pub task_exited: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, PartialEq)]
|
||||
@@ -108,8 +111,15 @@ impl DownloadManager {
|
||||
.lock()
|
||||
.map_err(|_| anyhow::anyhow!("Failed to acquire lock"))?;
|
||||
|
||||
if downloads.contains_key(&model_id) {
|
||||
anyhow::bail!("Download already in progress");
|
||||
if let Some(existing) = downloads.get(&model_id) {
|
||||
if existing.status == DownloadStatus::Downloading {
|
||||
anyhow::bail!("Download already in progress");
|
||||
}
|
||||
if existing.status == DownloadStatus::Cancelled && !existing.task_exited {
|
||||
anyhow::bail!(
|
||||
"Download is being cancelled; wait for it to finish before restarting"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
downloads.insert(
|
||||
@@ -123,6 +133,7 @@ impl DownloadManager {
|
||||
speed_bps: None,
|
||||
eta_seconds: None,
|
||||
error: None,
|
||||
task_exited: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -148,6 +159,7 @@ impl DownloadManager {
|
||||
if let Some(progress) = downloads.get_mut(&model_id_clone) {
|
||||
progress.status = DownloadStatus::Completed;
|
||||
progress.progress_percent = 100.0;
|
||||
progress.task_exited = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,8 +174,11 @@ impl DownloadManager {
|
||||
|
||||
if let Ok(mut downloads) = downloads.lock() {
|
||||
if let Some(progress) = downloads.get_mut(&model_id_clone) {
|
||||
progress.status = DownloadStatus::Failed;
|
||||
if progress.status != DownloadStatus::Cancelled {
|
||||
progress.status = DownloadStatus::Failed;
|
||||
}
|
||||
progress.error = Some(e.to_string());
|
||||
progress.task_exited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +194,10 @@ impl DownloadManager {
|
||||
downloads: &DownloadMap,
|
||||
model_id: &str,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let client = reqwest::Client::new();
|
||||
let client = reqwest::Client::builder()
|
||||
.connect_timeout(std::time::Duration::from_secs(30))
|
||||
.read_timeout(std::time::Duration::from_secs(60))
|
||||
.build()?;
|
||||
let mut response = client.get(url).send().await?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
@@ -217,7 +235,7 @@ impl DownloadManager {
|
||||
|
||||
if should_cancel {
|
||||
let _ = tokio::fs::remove_file(&partial_path).await;
|
||||
return Ok(());
|
||||
anyhow::bail!("Download cancelled");
|
||||
}
|
||||
|
||||
file.write_all(&chunk).await?;
|
||||
@@ -264,10 +282,10 @@ impl DownloadManager {
|
||||
pub fn clear_completed(&self, model_id: &str) {
|
||||
if let Ok(mut downloads) = self.downloads.lock() {
|
||||
if let Some(progress) = downloads.get(model_id) {
|
||||
if progress.status == DownloadStatus::Completed
|
||||
let is_terminal = progress.status == DownloadStatus::Completed
|
||||
|| progress.status == DownloadStatus::Failed
|
||||
|| progress.status == DownloadStatus::Cancelled
|
||||
{
|
||||
|| progress.status == DownloadStatus::Cancelled;
|
||||
if is_terminal && progress.task_exited {
|
||||
downloads.remove(model_id);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user