Fix phantom duplicate tracks created on Merged file ingestion
When the mover returns MoveOutcome::Merged (destination already exists, source deleted), approve_and_finalize was checking only file_hash to detect duplicates. Since the second ingestion had a different hash (different quality/mastering), it bypassed the check and created a phantom track record pointing to an existing storage_path with the wrong hash (of the now-deleted source file). Added a second dedup check by storage_path: if a non-hidden track already exists at that path, mark pending as 'merged' instead of inserting a new track row. This prevents phantom entries for any subsequent ingestion of a different-quality version of an already stored file. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -334,18 +334,31 @@ pub async fn approve_and_finalize(
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
|
||||
// Check if track already exists (e.g. previously approved but pending not cleaned up)
|
||||
// Check if track already exists by file_hash (re-approval of same file)
|
||||
let existing: Option<(i64,)> = sqlx::query_as("SELECT id FROM tracks WHERE file_hash = $1")
|
||||
.bind(&pt.file_hash)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
if let Some((track_id,)) = existing {
|
||||
// Already finalized — just mark pending as approved
|
||||
update_pending_status(pool, pending_id, "approved", None).await?;
|
||||
return Ok(track_id);
|
||||
}
|
||||
|
||||
// Check if track already exists by storage_path (Merged: different quality file landed
|
||||
// at the same destination, source was deleted — don't create a phantom duplicate)
|
||||
let existing_path: Option<(i64,)> = sqlx::query_as(
|
||||
"SELECT id FROM tracks WHERE storage_path = $1 AND NOT hidden"
|
||||
)
|
||||
.bind(storage_path)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
if let Some((track_id,)) = existing_path {
|
||||
update_pending_status(pool, pending_id, "merged", None).await?;
|
||||
return Ok(track_id);
|
||||
}
|
||||
|
||||
let artist_name = pt.norm_artist.as_deref().unwrap_or("Unknown Artist");
|
||||
let artist_id = upsert_artist(pool, artist_name).await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user