feat: complete task 6 - fix stale notification pruning to avoid SQLite parameter limit
This commit is contained in:
@@ -113,7 +113,7 @@ func SyncArtistDiscography(
|
||||
|
||||
// Build the set of RGIDs present in this sync so we can drop only the rows
|
||||
// that disappeared, leaving the rest (and their notification markers) intact.
|
||||
synced := make([]any, 0, len(filtered))
|
||||
synced := make([]string, 0, len(filtered))
|
||||
for _, rg := range filtered {
|
||||
synced = append(synced, rg.ID)
|
||||
}
|
||||
@@ -121,24 +121,55 @@ func SyncArtistDiscography(
|
||||
// Drop notification markers for releases that are gone. This runs before the
|
||||
// external_releases delete so the FK on notifications_sent.rgid stays valid
|
||||
// (we only ever delete from notifications_sent here).
|
||||
// Process in chunks to avoid SQLite parameter limits (default limit is 999).
|
||||
if len(synced) > 0 {
|
||||
placeholders := strings.Repeat("?,", len(synced))
|
||||
placeholders = placeholders[:len(placeholders)-1]
|
||||
query := fmt.Sprintf(
|
||||
"DELETE FROM notifications_sent WHERE rgid IN (SELECT rgid FROM external_releases WHERE artist_id = ? AND rgid NOT IN (%s))",
|
||||
placeholders,
|
||||
)
|
||||
args := append([]any{artistID}, synced...)
|
||||
if _, err := tx.Exec(query, args...); err != nil {
|
||||
return nil, fmt.Errorf("sync artist discography: prune stale notifications: %w", err)
|
||||
const chunkSize = 500
|
||||
for i := 0; i < len(synced); i += chunkSize {
|
||||
end := i + chunkSize
|
||||
if end > len(synced) {
|
||||
end = len(synced)
|
||||
}
|
||||
chunk := synced[i:end]
|
||||
|
||||
placeholders := strings.Repeat("?,", len(chunk))
|
||||
placeholders = placeholders[:len(placeholders)-1]
|
||||
query := fmt.Sprintf(
|
||||
"DELETE FROM notifications_sent WHERE rgid IN (SELECT rgid FROM external_releases WHERE artist_id = ? AND rgid NOT IN (%s))",
|
||||
placeholders,
|
||||
)
|
||||
args := make([]any, 1+len(chunk))
|
||||
args[0] = artistID
|
||||
for i, v := range chunk {
|
||||
args[i+1] = v
|
||||
}
|
||||
if _, err := tx.Exec(query, args...); err != nil {
|
||||
return nil, fmt.Errorf("sync artist discography: prune stale notifications (chunk %d-%d): %w", i, end, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove external_release rows that are no longer part of the discography.
|
||||
delQuery := fmt.Sprintf(
|
||||
"DELETE FROM external_releases WHERE artist_id = ? AND rgid NOT IN (%s)",
|
||||
placeholders,
|
||||
)
|
||||
if _, err := tx.Exec(delQuery, args...); err != nil {
|
||||
return nil, fmt.Errorf("sync artist discography: delete stale releases: %w", err)
|
||||
// Process in chunks to avoid SQLite parameter limits.
|
||||
for i := 0; i < len(synced); i += chunkSize {
|
||||
end := i + chunkSize
|
||||
if end > len(synced) {
|
||||
end = len(synced)
|
||||
}
|
||||
chunk := synced[i:end]
|
||||
|
||||
placeholders := strings.Repeat("?,", len(chunk))
|
||||
placeholders = placeholders[:len(placeholders)-1]
|
||||
delQuery := fmt.Sprintf(
|
||||
"DELETE FROM external_releases WHERE artist_id = ? AND rgid NOT IN (%s)",
|
||||
placeholders,
|
||||
)
|
||||
args := make([]any, 1+len(chunk))
|
||||
args[0] = artistID
|
||||
for i, v := range chunk {
|
||||
args[i+1] = v
|
||||
}
|
||||
if _, err := tx.Exec(delQuery, args...); err != nil {
|
||||
return nil, fmt.Errorf("sync artist discography: delete stale releases (chunk %d-%d): %w", i, end, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No releases this sync: the artist may have an empty discography. Drop
|
||||
|
||||
Reference in New Issue
Block a user