2 Commits

Author SHA1 Message Date
ab
3f2013e9d5 Merge pull request 'Fix phantom duplicate tracks created on Merged file ingestion' (#3) from DEV into main
All checks were successful
Publish Metadata Agent Image / build-and-push-image (push) Successful in 1m47s
Publish Web Player Image / build-and-push-image (push) Successful in 1m41s
Publish Server Image / build-and-push-image (push) Successful in 3m1s
Reviewed-on: #3
2026-03-19 23:43:36 +00:00
cc3ef04cbe Fix phantom duplicate tracks created on Merged file ingestion
All checks were successful
Publish Metadata Agent Image (dev) / build-and-push-image (push) Successful in 1m16s
Publish Web Player Image (dev) / build-and-push-image (push) Successful in 1m10s
Publish Server Image / build-and-push-image (push) Successful in 2m36s
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>
2026-03-19 23:37:33 +00:00

View File

@@ -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?;