mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-03 20:47:35 +03:00
Remove current Image Cache implementation
This commit is contained in:
parent
c430401ea9
commit
38bde0ddba
6 changed files with 28 additions and 167 deletions
|
@ -45,8 +45,7 @@ func CreateNativeAPIRouter() *nativeapi.Router {
|
|||
func CreateSubsonicAPIRouter() *subsonic.Router {
|
||||
sqlDB := db.Db()
|
||||
dataStore := persistence.New(sqlDB)
|
||||
artworkCache := core.GetImageCache()
|
||||
artwork := core.NewArtwork(dataStore, artworkCache)
|
||||
artwork := core.NewArtwork(dataStore)
|
||||
transcoderTranscoder := transcoder.New()
|
||||
transcodingCache := core.GetTranscodingCache()
|
||||
mediaStreamer := core.NewMediaStreamer(dataStore, transcoderTranscoder, transcodingCache)
|
||||
|
@ -80,11 +79,8 @@ func createScanner() scanner.Scanner {
|
|||
sqlDB := db.Db()
|
||||
dataStore := persistence.New(sqlDB)
|
||||
playlists := core.NewPlaylists(dataStore)
|
||||
artworkCache := core.GetImageCache()
|
||||
artwork := core.NewArtwork(dataStore, artworkCache)
|
||||
cacheWarmer := core.NewCacheWarmer(artwork, artworkCache)
|
||||
broker := events.GetBroker()
|
||||
scannerScanner := scanner.New(dataStore, playlists, cacheWarmer, broker)
|
||||
scannerScanner := scanner.New(dataStore, playlists, broker)
|
||||
return scannerScanner
|
||||
}
|
||||
|
||||
|
|
|
@ -2,18 +2,13 @@ package core
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
_ "image/gif"
|
||||
_ "image/png"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/resources"
|
||||
"github.com/navidrome/navidrome/utils/cache"
|
||||
_ "golang.org/x/image/webp"
|
||||
)
|
||||
|
||||
|
@ -21,44 +16,14 @@ type Artwork interface {
|
|||
Get(ctx context.Context, id string, size int) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
type ArtworkCache cache.FileCache
|
||||
|
||||
func NewArtwork(ds model.DataStore, cache ArtworkCache) Artwork {
|
||||
return &artwork{ds: ds, cache: cache}
|
||||
func NewArtwork(ds model.DataStore) Artwork {
|
||||
return &artwork{ds: ds}
|
||||
}
|
||||
|
||||
type artwork struct {
|
||||
ds model.DataStore
|
||||
cache cache.FileCache
|
||||
ds model.DataStore
|
||||
}
|
||||
|
||||
func (a *artwork) Get(ctx context.Context, id string, size int) (io.ReadCloser, error) {
|
||||
return resources.FS().Open(consts.PlaceholderAlbumArt)
|
||||
}
|
||||
|
||||
type imageInfo struct {
|
||||
a *artwork
|
||||
id string
|
||||
path string
|
||||
size int
|
||||
lastUpdate time.Time
|
||||
}
|
||||
|
||||
func (ci *imageInfo) Key() string {
|
||||
return fmt.Sprintf("%s.%d.%s.%d", ci.path, ci.size, ci.lastUpdate.Format(time.RFC3339Nano), conf.Server.CoverJpegQuality)
|
||||
}
|
||||
|
||||
var (
|
||||
onceImageCache sync.Once
|
||||
instanceImageCache ArtworkCache
|
||||
)
|
||||
|
||||
func GetImageCache() ArtworkCache {
|
||||
onceImageCache.Do(func() {
|
||||
instanceImageCache = cache.NewFileCache("Image", conf.Server.ImageCacheSize, consts.ImageCacheDir, consts.DefaultImageCacheMaxItems,
|
||||
func(ctx context.Context, arg cache.Item) (io.Reader, error) {
|
||||
return nil, nil
|
||||
})
|
||||
})
|
||||
return instanceImageCache
|
||||
}
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/utils/pool"
|
||||
)
|
||||
|
||||
type CacheWarmer interface {
|
||||
AddAlbum(ctx context.Context, albumID string)
|
||||
Flush(ctx context.Context)
|
||||
}
|
||||
|
||||
func NewCacheWarmer(artwork Artwork, artworkCache ArtworkCache) CacheWarmer {
|
||||
w := &warmer{
|
||||
artwork: artwork,
|
||||
artworkCache: artworkCache,
|
||||
albums: map[string]struct{}{},
|
||||
}
|
||||
p, err := pool.NewPool("artwork", 3, w.execute)
|
||||
if err != nil {
|
||||
log.Error(context.Background(), "Error creating pool for Album Artwork Cache Warmer", err)
|
||||
} else {
|
||||
w.pool = p
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
type warmer struct {
|
||||
pool *pool.Pool
|
||||
artwork Artwork
|
||||
artworkCache ArtworkCache
|
||||
albums map[string]struct{}
|
||||
}
|
||||
|
||||
func (w *warmer) AddAlbum(ctx context.Context, albumID string) {
|
||||
if albumID == "" {
|
||||
return
|
||||
}
|
||||
w.albums[albumID] = struct{}{}
|
||||
}
|
||||
|
||||
func (w *warmer) waitForCacheReady(ctx context.Context) {
|
||||
for !w.artworkCache.Ready(ctx) {
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *warmer) Flush(ctx context.Context) {
|
||||
if conf.Server.DevPreCacheAlbumArtwork {
|
||||
w.waitForCacheReady(ctx)
|
||||
if w.artworkCache.Available(ctx) {
|
||||
if w.pool == nil || len(w.albums) == 0 {
|
||||
return
|
||||
}
|
||||
log.Info(ctx, "Pre-caching album artworks", "numAlbums", len(w.albums))
|
||||
for id := range w.albums {
|
||||
w.pool.Submit(artworkItem{albumID: id})
|
||||
}
|
||||
} else {
|
||||
log.Warn(ctx, "Cache warmer is not available as ImageCache is DISABLED")
|
||||
}
|
||||
}
|
||||
w.albums = map[string]struct{}{}
|
||||
}
|
||||
|
||||
func (w *warmer) execute(workload interface{}) {
|
||||
ctx := context.Background()
|
||||
item := workload.(artworkItem)
|
||||
log.Trace(ctx, "Pre-caching album artwork", "albumID", item.albumID)
|
||||
r, err := w.artwork.Get(ctx, item.albumID, 0)
|
||||
if err != nil {
|
||||
log.Warn("Error pre-caching artwork from album", "id", item.albumID, err)
|
||||
return
|
||||
}
|
||||
defer r.Close()
|
||||
_, _ = io.Copy(io.Discard, r)
|
||||
}
|
||||
|
||||
type artworkItem struct {
|
||||
albumID string
|
||||
}
|
|
@ -11,10 +11,8 @@ var Set = wire.NewSet(
|
|||
NewArtwork,
|
||||
NewMediaStreamer,
|
||||
GetTranscodingCache,
|
||||
GetImageCache,
|
||||
NewArchiver,
|
||||
NewExternalMetadata,
|
||||
NewCacheWarmer,
|
||||
NewPlayers,
|
||||
agents.New,
|
||||
transcoder.New,
|
||||
|
|
|
@ -40,13 +40,12 @@ type FolderScanner interface {
|
|||
var isScanning sync.Mutex
|
||||
|
||||
type scanner struct {
|
||||
folders map[string]FolderScanner
|
||||
status map[string]*scanStatus
|
||||
lock *sync.RWMutex
|
||||
ds model.DataStore
|
||||
pls core.Playlists
|
||||
cacheWarmer core.CacheWarmer
|
||||
broker events.Broker
|
||||
folders map[string]FolderScanner
|
||||
status map[string]*scanStatus
|
||||
lock *sync.RWMutex
|
||||
ds model.DataStore
|
||||
pls core.Playlists
|
||||
broker events.Broker
|
||||
}
|
||||
|
||||
type scanStatus struct {
|
||||
|
@ -56,15 +55,14 @@ type scanStatus struct {
|
|||
lastUpdate time.Time
|
||||
}
|
||||
|
||||
func New(ds model.DataStore, playlists core.Playlists, cacheWarmer core.CacheWarmer, broker events.Broker) Scanner {
|
||||
func New(ds model.DataStore, playlists core.Playlists, broker events.Broker) Scanner {
|
||||
s := &scanner{
|
||||
ds: ds,
|
||||
pls: playlists,
|
||||
cacheWarmer: cacheWarmer,
|
||||
broker: broker,
|
||||
folders: map[string]FolderScanner{},
|
||||
status: map[string]*scanStatus{},
|
||||
lock: &sync.RWMutex{},
|
||||
ds: ds,
|
||||
pls: playlists,
|
||||
broker: broker,
|
||||
folders: map[string]FolderScanner{},
|
||||
status: map[string]*scanStatus{},
|
||||
lock: &sync.RWMutex{},
|
||||
}
|
||||
s.loadFolders()
|
||||
return s
|
||||
|
@ -143,7 +141,6 @@ func (s *scanner) RescanAll(ctx context.Context, fullRescan bool) error {
|
|||
}
|
||||
defer isScanning.Unlock()
|
||||
|
||||
defer s.cacheWarmer.Flush(ctx)
|
||||
var hasError bool
|
||||
for folder := range s.folders {
|
||||
err := s.rescan(ctx, folder, fullRescan)
|
||||
|
@ -245,5 +242,5 @@ func (s *scanner) loadFolders() {
|
|||
}
|
||||
|
||||
func (s *scanner) newScanner(f model.MediaFolder) FolderScanner {
|
||||
return NewTagScanner(f.Path, s.ds, s.pls, s.cacheWarmer)
|
||||
return NewTagScanner(f.Path, s.ds, s.pls)
|
||||
}
|
||||
|
|
|
@ -22,20 +22,18 @@ import (
|
|||
)
|
||||
|
||||
type TagScanner struct {
|
||||
rootFolder string
|
||||
ds model.DataStore
|
||||
cacheWarmer core.CacheWarmer
|
||||
plsSync *playlistImporter
|
||||
cnt *counters
|
||||
mapper *mediaFileMapper
|
||||
rootFolder string
|
||||
ds model.DataStore
|
||||
plsSync *playlistImporter
|
||||
cnt *counters
|
||||
mapper *mediaFileMapper
|
||||
}
|
||||
|
||||
func NewTagScanner(rootFolder string, ds model.DataStore, playlists core.Playlists, cacheWarmer core.CacheWarmer) *TagScanner {
|
||||
func NewTagScanner(rootFolder string, ds model.DataStore, playlists core.Playlists) *TagScanner {
|
||||
return &TagScanner{
|
||||
rootFolder: rootFolder,
|
||||
plsSync: newPlaylistImporter(ds, playlists, rootFolder),
|
||||
ds: ds,
|
||||
cacheWarmer: cacheWarmer,
|
||||
rootFolder: rootFolder,
|
||||
plsSync: newPlaylistImporter(ds, playlists, rootFolder),
|
||||
ds: ds,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,7 +238,6 @@ func (s *TagScanner) processDeletedDir(ctx context.Context, allFSDirs dirMap, di
|
|||
|
||||
for _, t := range mfs {
|
||||
buffer.accumulate(t)
|
||||
s.cacheWarmer.AddAlbum(ctx, t.AlbumID)
|
||||
}
|
||||
|
||||
err = buffer.flush()
|
||||
|
@ -323,11 +320,6 @@ func (s *TagScanner) processChangedDir(ctx context.Context, allFSDirs dirMap, di
|
|||
}
|
||||
}
|
||||
|
||||
// Pre cache all changed album artwork
|
||||
for albumID := range buffer.album {
|
||||
s.cacheWarmer.AddAlbum(ctx, albumID)
|
||||
}
|
||||
|
||||
err = buffer.flush()
|
||||
log.Info(ctx, "Finished processing changed folder", "dir", dir, "updated", numUpdatedTracks,
|
||||
"deleted", numPurgedTracks, "elapsed", time.Since(start))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue