fix(model): exclude blur hash fields from full-row writes

Scanner and maintenance paths build fresh entities with empty blur hash
fields, so every ordinary refresh erased the computed hash and caused a
double Finamp cover refetch (fake, then real again). The fields are now
read-only projections (structs:"-"): only UpdateBlurHash writes them.
This commit is contained in:
Deluan 2026-07-17 12:57:33 -04:00
parent c4ca3dca5e
commit 9ac2c6a5e3
4 changed files with 16 additions and 7 deletions

View File

@ -68,9 +68,10 @@ type Album struct {
CreatedAt time.Time `structs:"created_at" json:"createdAt"` // Oldest CreatedAt for all songs in this album
UpdatedAt time.Time `structs:"updated_at" json:"updatedAt"` // Newest UpdatedAt for all songs in this album
// BlurHash of the album cover, computed asynchronously from the served artwork.
BlurHash string `structs:"blur_hash" json:"blurHash,omitempty" hash:"ignore"`
BlurHashUpdatedAt *time.Time `structs:"blur_hash_updated_at" json:"-" hash:"ignore"`
// BlurHash of the album cover, computed asynchronously from the served artwork. Excluded from
// full-row writes (structs:"-"): only UpdateBlurHash writes it, so scans can't erase it.
BlurHash string `structs:"-" json:"blurHash,omitempty" hash:"ignore"`
BlurHashUpdatedAt *time.Time `structs:"-" json:"-" hash:"ignore"`
}
func (a Album) CoverArtID() ArtworkID {

View File

@ -42,8 +42,8 @@ type Artist struct {
CreatedAt *time.Time `structs:"created_at" json:"createdAt,omitempty"`
UpdatedAt *time.Time `structs:"updated_at" json:"updatedAt,omitempty"`
BlurHash string `structs:"blur_hash" json:"blurHash,omitempty" hash:"ignore"`
BlurHashUpdatedAt *time.Time `structs:"blur_hash_updated_at" json:"-" hash:"ignore"`
BlurHash string `structs:"-" json:"blurHash,omitempty" hash:"ignore"`
BlurHashUpdatedAt *time.Time `structs:"-" json:"-" hash:"ignore"`
}
type ArtistStats struct {

View File

@ -31,8 +31,8 @@ type Playlist struct {
CreatedAt time.Time `structs:"created_at" json:"createdAt"`
UpdatedAt time.Time `structs:"updated_at" json:"updatedAt"`
BlurHash string `structs:"blur_hash" json:"blurHash,omitempty" hash:"ignore"`
BlurHashUpdatedAt *time.Time `structs:"blur_hash_updated_at" json:"-" hash:"ignore"`
BlurHash string `structs:"-" json:"blurHash,omitempty" hash:"ignore"`
BlurHashUpdatedAt *time.Time `structs:"-" json:"-" hash:"ignore"`
// SmartPlaylist attributes
Rules *criteria.Criteria `structs:"rules" json:"rules"`

View File

@ -928,5 +928,13 @@ var _ = Describe("AlbumRepository.UpdateBlurHash", func() {
Expect(updated.BlurHashUpdatedAt.Equal(version)).To(BeTrue())
// The targeted update must not touch the row's own timestamps.
Expect(updated.UpdatedAt).To(Equal(al.UpdatedAt))
// A full-row Put (e.g. a scanner refresh with empty BlurHash fields) must preserve the hash.
updated.BlurHash = ""
updated.BlurHashUpdatedAt = nil
Expect(repo.Put(updated)).To(Succeed())
after, err := repo.Get(al.ID)
Expect(err).ToNot(HaveOccurred())
Expect(after.BlurHash).To(Equal("LKO2?U%2Tw=w]~RBVZRi};RPxuwH"))
})
})