mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-04 13:07:36 +03:00
Move album refresh to scanner
This commit is contained in:
parent
566ae93950
commit
2f90fc9bd4
5 changed files with 103 additions and 103 deletions
|
@ -54,6 +54,5 @@ type AlbumRepository interface {
|
|||
GetAll(...QueryOptions) (Albums, error)
|
||||
GetAllWithoutGenres(...QueryOptions) (Albums, error)
|
||||
Search(q string, offset int, size int) (Albums, error)
|
||||
Refresh(ids ...string) error
|
||||
AnnotatedRepository
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ import (
|
|||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/utils"
|
||||
"github.com/navidrome/navidrome/utils/slice"
|
||||
)
|
||||
|
||||
type albumRepository struct {
|
||||
|
@ -142,38 +140,6 @@ func (r *albumRepository) GetAllWithoutGenres(options ...model.QueryOptions) (mo
|
|||
return res, err
|
||||
}
|
||||
|
||||
func (r *albumRepository) Refresh(ids ...string) error {
|
||||
chunks := utils.BreakUpStringSlice(ids, 100)
|
||||
for _, chunk := range chunks {
|
||||
err := r.refresh(chunk...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *albumRepository) refresh(ids ...string) error {
|
||||
mfRepo := NewMediaFileRepository(r.ctx, r.ormer)
|
||||
mfs, err := mfRepo.GetAll(model.QueryOptions{Filters: Eq{"album_id": ids}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(mfs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
grouped := slice.Group(mfs, func(m model.MediaFile) string { return m.AlbumID })
|
||||
for _, songs := range grouped {
|
||||
a := model.MediaFiles(songs).ToAlbum()
|
||||
err := r.Put(&a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *albumRepository) purgeEmpty() error {
|
||||
del := Delete(r.tableName).Where("id not in (select distinct(album_id) from media_file)")
|
||||
c, err := r.executeSQL(del)
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
package scanner
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
)
|
||||
|
||||
type refreshBuffer struct {
|
||||
ctx context.Context
|
||||
ds model.DataStore
|
||||
album map[string]struct{}
|
||||
artist map[string]struct{}
|
||||
}
|
||||
|
||||
func newRefreshBuffer(ctx context.Context, ds model.DataStore) *refreshBuffer {
|
||||
return &refreshBuffer{
|
||||
ctx: ctx,
|
||||
ds: ds,
|
||||
album: map[string]struct{}{},
|
||||
artist: map[string]struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func (f *refreshBuffer) accumulate(mf model.MediaFile) {
|
||||
if mf.AlbumID != "" {
|
||||
f.album[mf.AlbumID] = struct{}{}
|
||||
}
|
||||
if mf.AlbumArtistID != "" {
|
||||
f.artist[mf.AlbumArtistID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
type refreshCallbackFunc = func(ids ...string) error
|
||||
|
||||
func (f *refreshBuffer) flushMap(m map[string]struct{}, entity string, refresh refreshCallbackFunc) error {
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
var ids []string
|
||||
for id := range m {
|
||||
ids = append(ids, id)
|
||||
delete(m, id)
|
||||
}
|
||||
if err := refresh(ids...); err != nil {
|
||||
log.Error(f.ctx, fmt.Sprintf("Error writing %ss to the DB", entity), err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *refreshBuffer) flush() error {
|
||||
err := f.flushMap(f.album, "album", f.ds.Album(f.ctx).Refresh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = f.flushMap(f.artist, "artist", f.ds.Artist(f.ctx).Refresh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
99
scanner/refresher.go
Normal file
99
scanner/refresher.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
package scanner
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/utils"
|
||||
"github.com/navidrome/navidrome/utils/slice"
|
||||
)
|
||||
|
||||
type refresher struct {
|
||||
ctx context.Context
|
||||
ds model.DataStore
|
||||
album map[string]struct{}
|
||||
artist map[string]struct{}
|
||||
}
|
||||
|
||||
func newRefresher(ctx context.Context, ds model.DataStore) *refresher {
|
||||
return &refresher{
|
||||
ctx: ctx,
|
||||
ds: ds,
|
||||
album: map[string]struct{}{},
|
||||
artist: map[string]struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func (f *refresher) accumulate(mf model.MediaFile) {
|
||||
if mf.AlbumID != "" {
|
||||
f.album[mf.AlbumID] = struct{}{}
|
||||
}
|
||||
if mf.AlbumArtistID != "" {
|
||||
f.artist[mf.AlbumArtistID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
type refreshCallbackFunc = func(ids ...string) error
|
||||
|
||||
func (f *refresher) flushMap(m map[string]struct{}, entity string, refresh refreshCallbackFunc) error {
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
var ids []string
|
||||
for id := range m {
|
||||
ids = append(ids, id)
|
||||
delete(m, id)
|
||||
}
|
||||
if err := refresh(ids...); err != nil {
|
||||
log.Error(f.ctx, fmt.Sprintf("Error writing %ss to the DB", entity), err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *refresher) chunkRefreshAlbums(ids ...string) error {
|
||||
chunks := utils.BreakUpStringSlice(ids, 100)
|
||||
for _, chunk := range chunks {
|
||||
err := f.refreshAlbums(chunk...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *refresher) refreshAlbums(ids ...string) error {
|
||||
mfs, err := f.ds.MediaFile(f.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"album_id": ids}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(mfs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
repo := f.ds.Album(f.ctx)
|
||||
grouped := slice.Group(mfs, func(m model.MediaFile) string { return m.AlbumID })
|
||||
for _, songs := range grouped {
|
||||
a := model.MediaFiles(songs).ToAlbum()
|
||||
err := repo.Put(&a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *refresher) flush() error {
|
||||
err := f.flushMap(f.album, "album", f.chunkRefreshAlbums)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = f.flushMap(f.artist, "artist", f.ds.Artist(f.ctx).Refresh) // TODO Move Artist Refresh out of persistence
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -225,7 +225,7 @@ func (s *TagScanner) getDeletedDirs(ctx context.Context, fsDirs dirMap, dbDirs m
|
|||
|
||||
func (s *TagScanner) processDeletedDir(ctx context.Context, dir string) error {
|
||||
start := time.Now()
|
||||
buffer := newRefreshBuffer(ctx, s.ds)
|
||||
buffer := newRefresher(ctx, s.ds)
|
||||
|
||||
mfs, err := s.ds.MediaFile(ctx).FindAllByPath(dir)
|
||||
if err != nil {
|
||||
|
@ -250,7 +250,7 @@ func (s *TagScanner) processDeletedDir(ctx context.Context, dir string) error {
|
|||
|
||||
func (s *TagScanner) processChangedDir(ctx context.Context, dir string, fullScan bool) error {
|
||||
start := time.Now()
|
||||
buffer := newRefreshBuffer(ctx, s.ds)
|
||||
buffer := newRefresher(ctx, s.ds)
|
||||
|
||||
// Load folder's current tracks from DB into a map
|
||||
currentTracks := map[string]model.MediaFile{}
|
||||
|
@ -334,7 +334,7 @@ func (s *TagScanner) processChangedDir(ctx context.Context, dir string, fullScan
|
|||
return err
|
||||
}
|
||||
|
||||
func (s *TagScanner) deleteOrphanSongs(ctx context.Context, dir string, tracksToDelete map[string]model.MediaFile, buffer *refreshBuffer) (int, error) {
|
||||
func (s *TagScanner) deleteOrphanSongs(ctx context.Context, dir string, tracksToDelete map[string]model.MediaFile, buffer *refresher) (int, error) {
|
||||
numPurgedTracks := 0
|
||||
|
||||
log.Debug(ctx, "Deleting orphan tracks from DB", "dir", dir, "numTracks", len(tracksToDelete))
|
||||
|
@ -350,7 +350,7 @@ 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 *refreshBuffer) (int, error) {
|
||||
func (s *TagScanner) addOrUpdateTracksInDB(ctx context.Context, dir string, currentTracks map[string]model.MediaFile, filesToUpdate []string, buffer *refresher) (int, error) {
|
||||
numUpdatedTracks := 0
|
||||
|
||||
log.Trace(ctx, "Updating mediaFiles in DB", "dir", dir, "numFiles", len(filesToUpdate))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue