mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-01 07:21:17 +00:00
fix(scanner): copy created_at once per target when albums merge
The per-pair attribute copy let a later merged old album overwrite the target's created_at with its own, shifting the album's position in Recently Added depending on processing order. Split the copy: created_at stays under the per-target guard (copied once), while the cover fields copy per old→new pair so any merged old album can still contribute an uploaded cover.
This commit is contained in:
parent
f4c1431bdf
commit
7c27e9d5a3
@ -315,6 +315,13 @@ func (p *phaseMissingTracks) moveMatched(target, missing model.MediaFile) error
|
||||
log.Warn(p.ctx, "Scanner: Could not reassign album annotations", "from", oldAlbumID, "to", newAlbumID, err)
|
||||
}
|
||||
|
||||
// Keep created_at once per target, so moved albums don't resurface in "Recently Added"
|
||||
if err := tx.Album(p.ctx).CopyAttributes(oldAlbumID, newAlbumID, "created_at"); err != nil {
|
||||
if !errors.Is(err, model.ErrNotFound) {
|
||||
log.Warn(p.ctx, "Scanner: Could not copy album created_at", "from", oldAlbumID, "to", newAlbumID, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: RefreshPlayCounts will be called in later phases, so we don't need to call it here
|
||||
p.processedAlbumAnnotations[newAlbumID] = true
|
||||
}
|
||||
@ -323,8 +330,8 @@ func (p *phaseMissingTracks) moveMatched(target, missing model.MediaFile) error
|
||||
log.Trace(p.ctx, "Scanner: Skipping album annotation reassignment", "from", oldAlbumID, "to", newAlbumID)
|
||||
}
|
||||
|
||||
// Copy created_at/cover per old→new pair (not per target): with several old albums
|
||||
// merging into one, any of them may hold the uploaded cover; empty sources never copy.
|
||||
// Copy the cover per old→new pair (not per target): with several old albums
|
||||
// merging into one, any of them may hold it; empty sources never copy.
|
||||
pairKey := oldAlbumID + "\x00" + newAlbumID
|
||||
p.annotationMutex.RLock()
|
||||
copyDone := p.processedAlbumCopies[pairKey]
|
||||
@ -332,9 +339,9 @@ func (p *phaseMissingTracks) moveMatched(target, missing model.MediaFile) error
|
||||
if !copyDone {
|
||||
p.annotationMutex.Lock()
|
||||
if !p.processedAlbumCopies[pairKey] {
|
||||
if err := tx.Album(p.ctx).CopyAttributes(oldAlbumID, newAlbumID, "created_at", "uploaded_image", "cover_art_updated_at"); err != nil {
|
||||
if err := tx.Album(p.ctx).CopyAttributes(oldAlbumID, newAlbumID, "uploaded_image", "cover_art_updated_at"); err != nil {
|
||||
if !errors.Is(err, model.ErrNotFound) {
|
||||
log.Warn(p.ctx, "Scanner: Could not copy album attributes", "from", oldAlbumID, "to", newAlbumID, err)
|
||||
log.Warn(p.ctx, "Scanner: Could not copy album cover", "from", oldAlbumID, "to", newAlbumID, err)
|
||||
}
|
||||
}
|
||||
p.processedAlbumCopies[pairKey] = true
|
||||
|
||||
@ -874,9 +874,10 @@ var _ = Describe("phaseMissingTracks", func() {
|
||||
missing2 := model.MediaFile{ID: "mg-2", PID: "MG2", Path: "lib1/b.mp3", AlbumID: "old-2", LibraryID: 1}
|
||||
matched2 := model.MediaFile{ID: "mt-2", PID: "MG2", Path: "lib2/b.mp3", AlbumID: "new-album", LibraryID: 1}
|
||||
|
||||
firstTime := time.Date(2018, 3, 1, 0, 0, 0, 0, time.UTC)
|
||||
albumRepo.SetData(model.Albums{
|
||||
{ID: "old-1", LibraryID: 1},
|
||||
{ID: "old-2", LibraryID: 1, UploadedImage: "old-2_cover.jpg"},
|
||||
{ID: "old-1", LibraryID: 1, CreatedAt: firstTime},
|
||||
{ID: "old-2", LibraryID: 1, UploadedImage: "old-2_cover.jpg", CreatedAt: time.Date(2022, 9, 9, 0, 0, 0, 0, time.UTC)},
|
||||
{ID: "new-album", LibraryID: 1},
|
||||
})
|
||||
|
||||
@ -890,6 +891,8 @@ var _ = Describe("phaseMissingTracks", func() {
|
||||
newAlbum, err := albumRepo.Get("new-album")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(newAlbum.UploadedImage).To(Equal("old-2_cover.jpg"))
|
||||
// created_at copies once per target: the second merged album must not overwrite it
|
||||
Expect(newAlbum.CreatedAt).To(Equal(firstTime))
|
||||
})
|
||||
|
||||
It("should not copy album created_at when album ID does not change", func() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user