Fixed merge
This commit is contained in:
@@ -147,6 +147,27 @@ async fn merge_db(
|
||||
proposal: &MergeProposal,
|
||||
loser_ids: &[i64],
|
||||
) -> 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
|
||||
sqlx::query("UPDATE artists SET name = $2 WHERE id = $1")
|
||||
.bind(proposal.winner_artist_id)
|
||||
@@ -155,6 +176,15 @@ async fn merge_db(
|
||||
|
||||
// 2. Process album mappings from the proposal
|
||||
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)
|
||||
let src_exists: (bool,) = sqlx::query_as("SELECT EXISTS(SELECT 1 FROM albums WHERE id = $1)")
|
||||
.bind(mapping.source_album_id)
|
||||
|
||||
Reference in New Issue
Block a user