navidrome/scanner/refresher.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

116 lines
2.6 KiB
Go
Raw Normal View History

2022-12-19 18:08:39 +01:00
package scanner
import (
"context"
"fmt"
"path/filepath"
"strings"
2022-12-19 18:08:39 +01:00
"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{}
dirMap dirMap
2022-12-19 18:08:39 +01:00
}
func newRefresher(ctx context.Context, ds model.DataStore, dirMap dirMap) *refresher {
2022-12-19 18:08:39 +01:00
return &refresher{
ctx: ctx,
ds: ds,
album: map[string]struct{}{},
artist: map[string]struct{}{},
dirMap: dirMap,
2022-12-19 18:08:39 +01:00
}
}
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) refreshAlbumsChunked(ids ...string) error {
2022-12-19 18:08:39 +01:00
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 _, group := range grouped {
songs := model.MediaFiles(group)
a := songs.ToAlbum()
a.ImageFiles = f.getImageFiles(songs.Dirs())
2022-12-19 18:08:39 +01:00
err := repo.Put(&a)
if err != nil {
return err
}
}
return nil
}
func (f *refresher) getImageFiles(dirs []string) string {
var imageFiles []string
for _, dir := range dirs {
for _, img := range f.dirMap[dir].Images {
imageFiles = append(imageFiles, filepath.Join(dir, img))
}
}
return strings.Join(imageFiles, string(filepath.ListSeparator))
}
2022-12-19 18:08:39 +01:00
func (f *refresher) flush() error {
err := f.flushMap(f.album, "album", f.refreshAlbumsChunked)
2022-12-19 18:08:39 +01:00
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
}