mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-13 13:06:52 +00:00
fix: resolve deadlock, redownload failure, and UI issues
- Fix re-entrant deadlock in `legacy_download_queue_paths` by scoping DB lock - Ensure `release_registered_id` runs in `remove_download` even if cleanup fails - Add fallback to `std::fs::remove_file` if `trash::delete` fails - Ignore 'cannot be paused now' error in `detach_download_for_reconfigure` - Apply `break-all` and `whitespace-pre-wrap` to Toast messages to prevent UI overflow
This commit is contained in:
@@ -144,13 +144,15 @@ fn load_records(app_handle: &tauri::AppHandle) -> Result<Vec<DownloadOwnershipRe
|
||||
fn legacy_download_queue_paths(app_handle: &tauri::AppHandle) -> Result<Vec<PathBuf>, String> {
|
||||
let settings = crate::settings::load_settings(app_handle).ok();
|
||||
|
||||
let database = app_handle.state::<crate::db::DbState>();
|
||||
let connection = database.lock()?;
|
||||
let downloads = crate::db::load_downloads(&connection)?
|
||||
.into_iter()
|
||||
.map(|value| serde_json::from_str::<crate::ipc::DownloadItem>(&value))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|error| format!("Invalid download queue ownership data: {error}"))?;
|
||||
let downloads = {
|
||||
let database = app_handle.state::<crate::db::DbState>();
|
||||
let connection = database.lock()?;
|
||||
crate::db::load_downloads(&connection)?
|
||||
.into_iter()
|
||||
.map(|value| serde_json::from_str::<crate::ipc::DownloadItem>(&value))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|error| format!("Invalid download queue ownership data: {error}"))?
|
||||
};
|
||||
|
||||
let mut paths = Vec::new();
|
||||
for download in downloads {
|
||||
|
||||
+25
-10
@@ -2869,15 +2869,19 @@ async fn remove_download(
|
||||
crate::ipc::DownloadStateEvent::new(id.clone(), crate::ipc::DownloadStatus::Paused),
|
||||
);
|
||||
|
||||
if delete_assets {
|
||||
if let Some(path) = primary_path.as_deref() {
|
||||
remove_download_assets(path, &app_handle).await?;
|
||||
let cleanup_result = (|| async {
|
||||
if delete_assets {
|
||||
if let Some(path) = primary_path.as_deref() {
|
||||
remove_download_assets(path, &app_handle).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
crate::download_ownership::remove(&app_handle, &id)?;
|
||||
Ok::<(), String>(())
|
||||
})()
|
||||
.await;
|
||||
|
||||
crate::download_ownership::remove(&app_handle, &id)?;
|
||||
state.queue_manager.release_registered_id(&id).await;
|
||||
Ok(())
|
||||
cleanup_result
|
||||
}
|
||||
|
||||
async fn remove_download_assets(
|
||||
@@ -2889,8 +2893,12 @@ async fn remove_download_assets(
|
||||
}
|
||||
|
||||
if primary.exists() {
|
||||
trash::delete(primary)
|
||||
.map_err(|error| format!("failed to move downloaded file to Trash: {error}"))?;
|
||||
if let Err(e) = trash::delete(primary) {
|
||||
log::warn!("failed to move downloaded file to Trash, attempting hard delete: {}", e);
|
||||
if let Err(hard_err) = std::fs::remove_file(primary) {
|
||||
return Err(format!("failed to move downloaded file to Trash ({e}) and hard delete failed ({hard_err})"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for suffix in [".aria2", ".part", ".ytdl"] {
|
||||
@@ -2923,13 +2931,20 @@ async fn detach_download_for_reconfigure(
|
||||
|
||||
if let Some(gid) = gid.as_deref().filter(|gid| !gid.starts_with("native:")) {
|
||||
let removal_result = async {
|
||||
rpc_call(
|
||||
let pause_res = rpc_call(
|
||||
state.aria2_port.load(std::sync::atomic::Ordering::Relaxed),
|
||||
&state.aria2_secret,
|
||||
"aria2.forcePause",
|
||||
serde_json::json!([gid]),
|
||||
)
|
||||
.await?;
|
||||
.await;
|
||||
|
||||
if let Err(e) = pause_res {
|
||||
if !e.contains("cannot be paused now") {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
|
||||
wait_for_aria2_stopped(
|
||||
state.aria2_port.load(std::sync::atomic::Ordering::Relaxed),
|
||||
&state.aria2_secret,
|
||||
|
||||
Reference in New Issue
Block a user