From 7d2d6f021d9cc7210a3d1a3b451de73f51e53aad Mon Sep 17 00:00:00 2001 From: Connor Johnstone Date: Thu, 26 Mar 2026 17:38:16 -0400 Subject: [PATCH] Unified the track logic. Seems to work much better --- src/workers.rs | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/workers.rs b/src/workers.rs index 70a5d3c..a09985c 100644 --- a/src/workers.rs +++ b/src/workers.rs @@ -416,27 +416,38 @@ async fn process_tag( .await .map_err(|e| e.to_string())?; - // Ensure a wanted_item exists for this track (marks imported files as Owned) - // Check by MBID first, then by name+artist to avoid duplicates from MBID mismatches - let has_wanted = if let Some(ref mbid) = track.musicbrainz_id { + // Ensure a wanted_item exists for this track (marks imported files as Owned). + // Check by MBID first, then by name+artist to avoid duplicates from MBID mismatches. + // When found, link the wanted_item to this track via track_id so cleanup never + // deletes it (track_id is a direct link that can't break from MBID mismatches). + let found_wanted = if let Some(ref mbid) = track.musicbrainz_id { queries::wanted::find_by_mbid(conn, mbid) .await .map_err(|e| e.to_string())? - .is_some() } else { - false + None }; - let has_wanted = has_wanted || { + let found_wanted = if found_wanted.is_some() { + found_wanted + } else { // Also check by name + artist_id (normalize unicode dashes and case) let all_wanted = queries::wanted::list(conn, None, None) .await .unwrap_or_default(); let title_norm = normalize_for_match(track.title.as_deref().unwrap_or("")); all_wanted - .iter() - .any(|w| w.artist_id == track.artist_id && normalize_for_match(&w.name) == title_norm) + .into_iter() + .find(|w| w.artist_id == track.artist_id && normalize_for_match(&w.name) == title_norm) }; - if !has_wanted { + + // Link the wanted_item to this track so get_unwanted() won't delete it + if let Some(ref wanted) = found_wanted { + if wanted.track_id != Some(track.id) { + let _ = queries::wanted::update_track_id(conn, wanted.id, track.id).await; + } + } + + if found_wanted.is_none() { let item = queries::wanted::add( conn, queries::wanted::AddWantedItem { @@ -511,6 +522,14 @@ async fn trigger_pipeline_completion(state: &web::Data, pipeline_id: & Ok(unwanted) if !unwanted.is_empty() => { let count = unwanted.len(); for track in &unwanted { + tracing::info!( + id = track.id, + path = %track.file_path, + artist = ?track.artist, + title = ?track.title, + mbid = ?track.musicbrainz_id, + "deleting unwanted track" + ); let path = std::path::Path::new(&track.file_path); if path.exists() { if let Err(e) = std::fs::remove_file(path) {