fix: address fourth code review findings
- Fix FK constraint violation in SyncArtistDiscography: delete notifications_sent rows before external_releases to prevent constraint failure when re-syncing artists with prior notifications. - Implement per-artist type filtering: FilterReleaseGroups now accepts FilterOptions with IgnoreSingles/IgnoreCompilations flags, read from artist_settings table via getArtistFilterOptions. - Fix inconsistent error wrapping: GetExternalRelease now wraps errors with fmt.Errorf like all other functions in the package; updated test to use errors.Is for sql.ErrNoRows check. - Add tests: FilterReleaseGroups ignore singles/compilations, SyncArtistDiscography per-artist type filtering, and FK-safe resync.
This commit is contained in:
@@ -2,6 +2,7 @@ package musicbrainz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -51,8 +52,12 @@ func SyncArtistDiscography(
|
||||
return nil, fmt.Errorf("sync artist discography: fetch release groups for artist %s: %w", artistMBID, err)
|
||||
}
|
||||
|
||||
// Step 4: Apply filtering.
|
||||
filtered := FilterReleaseGroups(groups)
|
||||
// Step 4: Apply filtering with per-artist type preferences.
|
||||
opts, err := getArtistFilterOptions(db, artistMBID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("sync artist discography: read artist filter options: %w", err)
|
||||
}
|
||||
filtered := FilterReleaseGroups(groups, opts)
|
||||
|
||||
// Step 5: Upsert within a transaction — delete old entries first, then insert new ones.
|
||||
now := time.Now().UTC()
|
||||
@@ -80,6 +85,14 @@ func SyncArtistDiscography(
|
||||
rows.Close()
|
||||
|
||||
// Delete old entries for this artist to avoid stale records.
|
||||
// Must delete notifications_sent first to avoid FK violation since
|
||||
// notifications_sent.rgid references external_releases.rgid.
|
||||
if _, err := tx.Exec(
|
||||
"DELETE FROM notifications_sent WHERE rgid IN (SELECT rgid FROM external_releases WHERE artist_id = ?)",
|
||||
artistMBID,
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("sync artist discography: delete old notifications: %w", err)
|
||||
}
|
||||
if _, err := tx.Exec("DELETE FROM external_releases WHERE artist_id = ?", artistMBID); err != nil {
|
||||
return nil, fmt.Errorf("sync artist discography: delete old releases: %w", err)
|
||||
}
|
||||
@@ -115,3 +128,20 @@ func SyncArtistDiscography(
|
||||
|
||||
return releases, nil
|
||||
}
|
||||
|
||||
// getArtistFilterOptions reads per-artist type filtering preferences.
|
||||
// Defaults to no filtering if artist_settings row doesn't exist.
|
||||
func getArtistFilterOptions(db *database.DB, artistMBID string) (FilterOptions, error) {
|
||||
var opts FilterOptions
|
||||
err := db.Conn().QueryRow(
|
||||
"SELECT COALESCE(ignore_singles, 0), COALESCE(ignore_compilations, 0) FROM artist_settings WHERE id = ?",
|
||||
artistMBID,
|
||||
).Scan(&opts.IgnoreSingles, &opts.IgnoreCompilations)
|
||||
if err == sql.ErrNoRows {
|
||||
return opts, nil
|
||||
}
|
||||
if err != nil {
|
||||
return opts, fmt.Errorf("query artist filter options: %w", err)
|
||||
}
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user