Add new Artwork Cache Warmer

This commit is contained in:
Deluan
2022-12-23 12:28:22 -05:00
committed by Deluan Quintão
parent 8c1cd9c273
commit b6eb60f019
11 changed files with 501 additions and 215 deletions
+40 -26
View File
@@ -22,19 +22,23 @@ import (
)
type TagScanner struct {
rootFolder string
ds model.DataStore
plsSync *playlistImporter
cnt *counters
mapper *mediaFileMapper
rootFolder string
ds model.DataStore
plsSync *playlistImporter
cnt *counters
mapper *mediaFileMapper
cacheWarmer core.ArtworkCacheWarmer
}
func NewTagScanner(rootFolder string, ds model.DataStore, playlists core.Playlists) *TagScanner {
return &TagScanner{
rootFolder: rootFolder,
plsSync: newPlaylistImporter(ds, playlists, rootFolder),
ds: ds,
func NewTagScanner(rootFolder string, ds model.DataStore, playlists core.Playlists, cacheWarmer core.ArtworkCacheWarmer) FolderScanner {
s := &TagScanner{
rootFolder: rootFolder,
plsSync: newPlaylistImporter(ds, playlists, rootFolder),
ds: ds,
cacheWarmer: cacheWarmer,
}
return s
}
type dirMap map[string]dirStats
@@ -96,6 +100,7 @@ func (s *TagScanner) Scan(ctx context.Context, lastModifiedSince time.Time, prog
s.cnt = &counters{}
genres := newCachedGenreRepository(ctx, s.ds.Genre(ctx))
s.mapper = newMediaFileMapper(s.rootFolder, genres)
refresher := newRefresher(s.ds, s.cacheWarmer, allFSDirs)
foldersFound, walkerError := s.getRootFolderWalker(ctx)
for {
@@ -109,7 +114,7 @@ func (s *TagScanner) Scan(ctx context.Context, lastModifiedSince time.Time, prog
if s.folderHasChanged(folderStats, allDBDirs, lastModifiedSince) {
changedDirs = append(changedDirs, folderStats.Path)
log.Debug("Processing changed folder", "dir", folderStats.Path)
err := s.processChangedDir(ctx, allFSDirs, folderStats.Path, fullScan)
err := s.processChangedDir(ctx, refresher, fullScan, folderStats.Path)
if err != nil {
log.Error("Error updating folder in the DB", "dir", folderStats.Path, err)
}
@@ -128,7 +133,7 @@ func (s *TagScanner) Scan(ctx context.Context, lastModifiedSince time.Time, prog
}
for _, dir := range deletedDirs {
err := s.processDeletedDir(ctx, allFSDirs, dir)
err := s.processDeletedDir(ctx, refresher, dir)
if err != nil {
log.Error("Error removing deleted folder from DB", "dir", dir, err)
}
@@ -221,9 +226,8 @@ func (s *TagScanner) getDeletedDirs(ctx context.Context, fsDirs dirMap, dbDirs m
return deleted
}
func (s *TagScanner) processDeletedDir(ctx context.Context, allFSDirs dirMap, dir string) error {
func (s *TagScanner) processDeletedDir(ctx context.Context, refresher *refresher, dir string) error {
start := time.Now()
buffer := newRefresher(ctx, s.ds, allFSDirs)
mfs, err := s.ds.MediaFile(ctx).FindAllByPath(dir)
if err != nil {
@@ -237,17 +241,16 @@ func (s *TagScanner) processDeletedDir(ctx context.Context, allFSDirs dirMap, di
s.cnt.deleted += c
for _, t := range mfs {
buffer.accumulate(t)
refresher.accumulate(t)
}
err = buffer.flush()
err = refresher.flush(ctx)
log.Info(ctx, "Finished processing deleted folder", "dir", dir, "purged", len(mfs), "elapsed", time.Since(start))
return err
}
func (s *TagScanner) processChangedDir(ctx context.Context, allFSDirs dirMap, dir string, fullScan bool) error {
func (s *TagScanner) processChangedDir(ctx context.Context, refresher *refresher, fullScan bool, dir string) error {
start := time.Now()
buffer := newRefresher(ctx, s.ds, allFSDirs)
// Load folder's current tracks from DB into a map
currentTracks := map[string]model.MediaFile{}
@@ -296,7 +299,7 @@ func (s *TagScanner) processChangedDir(ctx context.Context, allFSDirs dirMap, di
}
// Force a refresh of the album and artist, to cater for cover art files
buffer.accumulate(c)
refresher.accumulate(c)
// Only leaves in orphanTracks the ones not found in the folder. After this loop any remaining orphanTracks
// are considered gone from the music folder and will be deleted from DB
@@ -307,33 +310,38 @@ func (s *TagScanner) processChangedDir(ctx context.Context, allFSDirs dirMap, di
numPurgedTracks := 0
if len(filesToUpdate) > 0 {
numUpdatedTracks, err = s.addOrUpdateTracksInDB(ctx, dir, currentTracks, filesToUpdate, buffer)
numUpdatedTracks, err = s.addOrUpdateTracksInDB(ctx, refresher, dir, currentTracks, filesToUpdate)
if err != nil {
return err
}
}
if len(orphanTracks) > 0 {
numPurgedTracks, err = s.deleteOrphanSongs(ctx, dir, orphanTracks, buffer)
numPurgedTracks, err = s.deleteOrphanSongs(ctx, refresher, dir, orphanTracks)
if err != nil {
return err
}
}
err = buffer.flush()
err = refresher.flush(ctx)
log.Info(ctx, "Finished processing changed folder", "dir", dir, "updated", numUpdatedTracks,
"deleted", numPurgedTracks, "elapsed", time.Since(start))
return err
}
func (s *TagScanner) deleteOrphanSongs(ctx context.Context, dir string, tracksToDelete map[string]model.MediaFile, buffer *refresher) (int, error) {
func (s *TagScanner) deleteOrphanSongs(
ctx context.Context,
refresher *refresher,
dir string,
tracksToDelete map[string]model.MediaFile,
) (int, error) {
numPurgedTracks := 0
log.Debug(ctx, "Deleting orphan tracks from DB", "dir", dir, "numTracks", len(tracksToDelete))
// Remaining tracks from DB that are not in the folder are deleted
for _, ct := range tracksToDelete {
numPurgedTracks++
buffer.accumulate(ct)
refresher.accumulate(ct)
if err := s.ds.MediaFile(ctx).Delete(ct.ID); err != nil {
return 0, err
}
@@ -342,7 +350,13 @@ func (s *TagScanner) deleteOrphanSongs(ctx context.Context, dir string, tracksTo
return numPurgedTracks, nil
}
func (s *TagScanner) addOrUpdateTracksInDB(ctx context.Context, dir string, currentTracks map[string]model.MediaFile, filesToUpdate []string, buffer *refresher) (int, error) {
func (s *TagScanner) addOrUpdateTracksInDB(
ctx context.Context,
refresher *refresher,
dir string,
currentTracks map[string]model.MediaFile,
filesToUpdate []string,
) (int, error) {
numUpdatedTracks := 0
log.Trace(ctx, "Updating mediaFiles in DB", "dir", dir, "numFiles", len(filesToUpdate))
@@ -367,7 +381,7 @@ func (s *TagScanner) addOrUpdateTracksInDB(ctx context.Context, dir string, curr
if err != nil {
return 0, err
}
buffer.accumulate(n)
refresher.accumulate(n)
numUpdatedTracks++
}
}