Fixed merge
All checks were successful
Publish Metadata Agent Image (dev) / build-and-push-image (push) Successful in 1m7s
Publish Web Player Image (dev) / build-and-push-image (push) Successful in 1m11s
Publish Server Image / build-and-push-image (push) Successful in 2m12s

This commit is contained in:
2026-03-19 14:16:45 +00:00
parent b1eaa1b6e9
commit 5fb8821709

View File

@@ -147,6 +147,27 @@ async fn merge_db(
proposal: &MergeProposal, proposal: &MergeProposal,
loser_ids: &[i64], loser_ids: &[i64],
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
// 0. Validate proposal — ensure winner and all album IDs belong to source artists
let source_ids: Vec<i64> = loser_ids.iter().copied()
.chain(std::iter::once(proposal.winner_artist_id))
.collect();
// Verify winner_artist_id is one of the source artists
if !source_ids.contains(&proposal.winner_artist_id) {
anyhow::bail!(
"winner_artist_id {} is not among source artists {:?}",
proposal.winner_artist_id, source_ids
);
}
// Build set of valid album IDs (albums that actually belong to source artists)
let mut valid_album_ids = std::collections::HashSet::<i64>::new();
for &src_id in &source_ids {
let rows: Vec<(i64,)> = sqlx::query_as("SELECT id FROM albums WHERE artist_id = $1")
.bind(src_id).fetch_all(&mut **tx).await?;
for (id,) in rows { valid_album_ids.insert(id); }
}
// 1. Rename winner artist to canonical name // 1. Rename winner artist to canonical name
sqlx::query("UPDATE artists SET name = $2 WHERE id = $1") sqlx::query("UPDATE artists SET name = $2 WHERE id = $1")
.bind(proposal.winner_artist_id) .bind(proposal.winner_artist_id)
@@ -155,6 +176,15 @@ async fn merge_db(
// 2. Process album mappings from the proposal // 2. Process album mappings from the proposal
for mapping in &proposal.album_mappings { for mapping in &proposal.album_mappings {
// Skip albums that don't belong to any source artist (LLM hallucinated IDs)
if !valid_album_ids.contains(&mapping.source_album_id) {
tracing::warn!(
album_id = mapping.source_album_id,
"Skipping album mapping: album does not belong to source artists"
);
continue;
}
// Skip if source was already processed (idempotent retry support) // Skip if source was already processed (idempotent retry support)
let src_exists: (bool,) = sqlx::query_as("SELECT EXISTS(SELECT 1 FROM albums WHERE id = $1)") let src_exists: (bool,) = sqlx::query_as("SELECT EXISTS(SELECT 1 FROM albums WHERE id = $1)")
.bind(mapping.source_album_id) .bind(mapping.source_album_id)