diff --git a/crates/lanspread-peer/src/handlers.rs b/crates/lanspread-peer/src/handlers.rs index 3ccf4d0..8adca68 100644 --- a/crates/lanspread-peer/src/handlers.rs +++ b/crates/lanspread-peer/src/handlers.rs @@ -321,7 +321,7 @@ pub async fn handle_download_game_files_command( peer_whitelist, file_peer_map, tx_notify_ui_clone.clone(), - cancel_token, + cancel_token.clone(), ) .await; @@ -398,8 +398,17 @@ pub async fn handle_download_game_files_command( } end_download_operation(&ctx_clone, &tx_notify_ui_clone, &download_id).await; download_state_guard.disarm(); - log::error!("Download failed for {download_id}: {e}"); - send_download_failed(&tx_notify_ui_clone, &download_id); + let download_was_cancelled = cancel_token.is_cancelled(); + if download_was_cancelled { + log::info!("Download cancelled for {download_id}: {e}"); + } else { + log::error!("Download failed for {download_id}: {e}"); + } + send_download_failed_unless_cancelled( + &tx_notify_ui_clone, + &download_id, + download_was_cancelled, + ); } } }); @@ -787,6 +796,19 @@ fn send_download_failed(tx_notify_ui: &UnboundedSender, id: &str) { } } +fn send_download_failed_unless_cancelled( + tx_notify_ui: &UnboundedSender, + id: &str, + cancelled: bool, +) -> bool { + if cancelled { + return false; + } + + send_download_failed(tx_notify_ui, id); + true +} + async fn end_download_operation(ctx: &Ctx, tx_notify_ui: &UnboundedSender, id: &str) { end_operation(ctx, tx_notify_ui, id).await; clear_active_download(ctx, id).await; @@ -1097,6 +1119,29 @@ mod tests { ) } + #[test] + fn cancelled_download_error_does_not_emit_failed_event() { + let (tx, mut rx) = mpsc::unbounded_channel(); + + let emitted = send_download_failed_unless_cancelled(&tx, "game", true); + + assert!(!emitted); + assert!(rx.try_recv().is_err()); + } + + #[test] + fn uncancelled_download_error_emits_failed_event() { + let (tx, mut rx) = mpsc::unbounded_channel(); + + let emitted = send_download_failed_unless_cancelled(&tx, "game", false); + + assert!(emitted); + assert!(matches!( + rx.try_recv(), + Ok(PeerEvent::DownloadGameFilesFailed { id }) if id == "game" + )); + } + async fn recv_event(rx: &mut mpsc::UnboundedReceiver) -> PeerEvent { tokio::time::timeout(Duration::from_secs(1), rx.recv()) .await