mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-01 07:21:17 +00:00
Write falls through to a real write when the liveness touch fails, and sweep retention now matches the recorded mime's extension so obsolete variants are reclaimed.
69 lines
1.9 KiB
Go
69 lines
1.9 KiB
Go
package artwork
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/navidrome/navidrome/log"
|
|
"github.com/navidrome/navidrome/model"
|
|
)
|
|
|
|
// pruneMinAge guards the window between artwork insert and item_artwork upsert.
|
|
const pruneMinAge = time.Hour
|
|
|
|
func Prune(ctx context.Context, ds model.DataStore, store *ImageStore) error {
|
|
repo := ds.Artwork(ctx)
|
|
// One grace cutoff for both the DB orphan check and the file sweep: files younger
|
|
// than the window may belong to acquisitions whose rows aren't committed yet.
|
|
cutoff := time.Now().Add(-pruneMinAge)
|
|
candidates, err := repo.GetOrphanHashes(cutoff)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(candidates) > 0 {
|
|
arts, err := repo.GetImages(candidates)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := repo.DeleteOrphans(cutoff, candidates); err != nil {
|
|
return err
|
|
}
|
|
// DeleteOrphans may spare candidates reacquired since the snapshot; only remove files
|
|
// for rows actually gone (absent from the post-delete re-read).
|
|
survivors, err := repo.GetImages(candidates)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
removed := 0
|
|
for _, h := range candidates {
|
|
if _, ok := survivors[h]; ok {
|
|
continue
|
|
}
|
|
// A spared fresh file is at worst a stray a later sweep reclaims; full
|
|
// worker/prune mutual exclusion is Phase 2's concern.
|
|
if err := store.Remove(h, arts[h].Mime, cutoff); err != nil {
|
|
log.Warn(ctx, "Prune: could not remove artwork file", "hash", h, err)
|
|
}
|
|
removed++
|
|
}
|
|
log.Info(ctx, "Prune: removed orphan artwork", "count", removed)
|
|
}
|
|
|
|
mimes, err := repo.GetAllMimes()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
removed, err := store.Sweep(cutoff, func(hash, ext string) bool {
|
|
// A known hash under a stale extension is a superseded mime variant — reclaim it.
|
|
m, ok := mimes[hash]
|
|
return ok && ext == extForMime(m)
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if removed > 0 {
|
|
log.Info(ctx, "Prune: swept stray artwork files", "count", removed)
|
|
}
|
|
return nil
|
|
}
|