mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-01 07:21:17 +00:00
refactor(artwork): name the service for its domain, not its role
Every other core interface is named for what it is -- Playlists, Library, Scrobbler, MediaStreamer -- while this one was artwork.Service, the only X.Service in the tree. It becomes artwork.Artwork/NewArtwork, and serving.go follows the type to artwork.go. ProvideImageStore was likewise the only "func Provide" in the repo; it is GetImageStore now, matching GetImageCache beside it. cmd/wire_gen.go regenerated via make wire.
This commit is contained in:
parent
1ceb8ca723
commit
0ba89dae49
@ -84,9 +84,9 @@ func CreateSubsonicAPIRouter(ctx context.Context) *subsonic.Router {
|
||||
sqlDB := db.Db()
|
||||
dataStore := persistence.New(sqlDB)
|
||||
fileCache := artwork.GetImageCache()
|
||||
imageStore := artwork.ProvideImageStore()
|
||||
imageStore := artwork.GetImageStore()
|
||||
fFmpeg := ffmpeg.New()
|
||||
service := artwork.NewService(dataStore, fileCache, imageStore, fFmpeg)
|
||||
artworkArtwork := artwork.NewArtwork(dataStore, fileCache, imageStore, fFmpeg)
|
||||
transcodingCache := stream.GetTranscodingCache()
|
||||
mediaStreamer := stream.NewMediaStreamer(dataStore, fFmpeg, transcodingCache)
|
||||
share := core.NewShare(dataStore)
|
||||
@ -106,7 +106,7 @@ func CreateSubsonicAPIRouter(ctx context.Context) *subsonic.Router {
|
||||
lyricsLyrics := lyrics.NewLyrics(dataStore, manager)
|
||||
transcodeDecider := stream.NewTranscodeDecider(dataStore, fFmpeg)
|
||||
sonicSonic := sonic.New(dataStore, manager, matcherMatcher)
|
||||
router := subsonic.New(dataStore, service, mediaStreamer, archiver, players, provider, modelScanner, broker, playlistsPlaylists, playTracker, share, playbackServer, metricsMetrics, lyricsLyrics, transcodeDecider, sonicSonic)
|
||||
router := subsonic.New(dataStore, artworkArtwork, mediaStreamer, archiver, players, provider, modelScanner, broker, playlistsPlaylists, playTracker, share, playbackServer, metricsMetrics, lyricsLyrics, transcodeDecider, sonicSonic)
|
||||
return router
|
||||
}
|
||||
|
||||
@ -114,9 +114,9 @@ func CreateJellyfinAPIRouter(ctx context.Context) *jellyfin.Router {
|
||||
sqlDB := db.Db()
|
||||
dataStore := persistence.New(sqlDB)
|
||||
fileCache := artwork.GetImageCache()
|
||||
imageStore := artwork.ProvideImageStore()
|
||||
imageStore := artwork.GetImageStore()
|
||||
fFmpeg := ffmpeg.New()
|
||||
service := artwork.NewService(dataStore, fileCache, imageStore, fFmpeg)
|
||||
artworkArtwork := artwork.NewArtwork(dataStore, fileCache, imageStore, fFmpeg)
|
||||
transcodingCache := stream.GetTranscodingCache()
|
||||
mediaStreamer := stream.NewMediaStreamer(dataStore, fFmpeg, transcodingCache)
|
||||
transcodeDecider := stream.NewTranscodeDecider(dataStore, fFmpeg)
|
||||
@ -132,7 +132,7 @@ func CreateJellyfinAPIRouter(ctx context.Context) *jellyfin.Router {
|
||||
provider := external.NewProvider(dataStore, agentsAgents, matcherMatcher)
|
||||
sonicSonic := sonic.New(dataStore, manager, matcherMatcher)
|
||||
lyricsLyrics := lyrics.NewLyrics(dataStore, manager)
|
||||
router := jellyfin.New(dataStore, service, mediaStreamer, transcodeDecider, players, playTracker, playlistsPlaylists, provider, sonicSonic, lyricsLyrics, broker)
|
||||
router := jellyfin.New(dataStore, artworkArtwork, mediaStreamer, transcodeDecider, players, playTracker, playlistsPlaylists, provider, sonicSonic, lyricsLyrics, broker)
|
||||
return router
|
||||
}
|
||||
|
||||
@ -140,14 +140,14 @@ func CreatePublicRouter() *public.Router {
|
||||
sqlDB := db.Db()
|
||||
dataStore := persistence.New(sqlDB)
|
||||
fileCache := artwork.GetImageCache()
|
||||
imageStore := artwork.ProvideImageStore()
|
||||
imageStore := artwork.GetImageStore()
|
||||
fFmpeg := ffmpeg.New()
|
||||
service := artwork.NewService(dataStore, fileCache, imageStore, fFmpeg)
|
||||
artworkArtwork := artwork.NewArtwork(dataStore, fileCache, imageStore, fFmpeg)
|
||||
transcodingCache := stream.GetTranscodingCache()
|
||||
mediaStreamer := stream.NewMediaStreamer(dataStore, fFmpeg, transcodingCache)
|
||||
share := core.NewShare(dataStore)
|
||||
archiver := core.NewArchiver(mediaStreamer, dataStore, share)
|
||||
router := public.New(dataStore, service, mediaStreamer, share, archiver)
|
||||
router := public.New(dataStore, artworkArtwork, mediaStreamer, share, archiver)
|
||||
return router
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ func GetPlaybackServer() playback.PlaybackServer {
|
||||
func CreateArtworkWorker() *artwork.Worker {
|
||||
sqlDB := db.Db()
|
||||
dataStore := persistence.New(sqlDB)
|
||||
imageStore := artwork.ProvideImageStore()
|
||||
imageStore := artwork.GetImageStore()
|
||||
broker := events.GetBroker()
|
||||
metricsMetrics := metrics.GetPrometheusInstance(dataStore)
|
||||
manager := plugins.GetManager(dataStore, broker, metricsMetrics)
|
||||
|
||||
@ -40,7 +40,7 @@ func representationTag(hash string, size int, square bool) string {
|
||||
return fmt.Sprintf("%s.%d.%v.%s", hash, size, square, formatQualityTag())
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
type Artwork interface {
|
||||
// Get serves resolved/provisional artwork; ErrUnavailable or model.ErrNotFound when
|
||||
// there is nothing to serve (absent, pending, dangling) — caller picks placeholder vs 404.
|
||||
Get(ctx context.Context, artID model.ArtworkID, size int, square bool) (*Image, error)
|
||||
@ -49,7 +49,7 @@ type Service interface {
|
||||
GetOrPlaceholder(ctx context.Context, id string, size int, square bool) (*Image, error)
|
||||
}
|
||||
|
||||
func NewService(ds model.DataStore, cache cache.FileCache, store *ImageStore, ffm ffmpeg.FFmpeg) Service {
|
||||
func NewArtwork(ds model.DataStore, cache cache.FileCache, store *ImageStore, ffm ffmpeg.FFmpeg) Artwork {
|
||||
return &service{ds: ds, cache: cache, store: store, ffmpeg: ffm}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Service", func() {
|
||||
var _ = Describe("Artwork", func() {
|
||||
var (
|
||||
ctx context.Context
|
||||
ds *tests.MockDataStore
|
||||
@ -33,7 +33,7 @@ var _ = Describe("Service", func() {
|
||||
ffm *tests.MockFFmpeg
|
||||
store *ImageStore
|
||||
imgCache cache.FileCache
|
||||
svc Service
|
||||
svc Artwork
|
||||
repoRoot string
|
||||
coverBytes []byte
|
||||
)
|
||||
@ -96,7 +96,7 @@ var _ = Describe("Service", func() {
|
||||
return arg.(artworkReader).Reader(ctx)
|
||||
})
|
||||
Eventually(func() bool { return imgCache.Available(ctx) }).Should(BeTrue())
|
||||
svc = NewService(ds, imgCache, store, ffm)
|
||||
svc = NewArtwork(ds, imgCache, store, ffm)
|
||||
})
|
||||
|
||||
Describe("found state", func() {
|
||||
@ -37,7 +37,7 @@ var _ = Describe("Acquisition → serve loop", func() {
|
||||
folderRepo *fakeFolderRepo
|
||||
libRepo *tests.MockLibraryRepo
|
||||
store *artwork.ImageStore
|
||||
svc artwork.Service
|
||||
svc artwork.Artwork
|
||||
worker *artwork.Worker
|
||||
coverBytes []byte
|
||||
)
|
||||
@ -102,7 +102,7 @@ var _ = Describe("Acquisition → serve loop", func() {
|
||||
})
|
||||
Eventually(func() bool { return imgCache.Available(ctx) }).Should(BeTrue())
|
||||
|
||||
svc = artwork.NewService(ds, imgCache, store, ffm)
|
||||
svc = artwork.NewArtwork(ds, imgCache, store, ffm)
|
||||
worker = artwork.NewWorker(ds, store, agents.GetAgents(ds, nil), ffm, events.NoopBroker(), imgCache)
|
||||
})
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ var (
|
||||
rctx context.Context
|
||||
rds *tests.MockDataStore
|
||||
rstore *artwork.ImageStore
|
||||
rsvc artwork.Service
|
||||
rsvc artwork.Artwork
|
||||
rworker *artwork.Worker
|
||||
fakeFS *storagetest.FakeFS
|
||||
)
|
||||
@ -125,7 +125,7 @@ func setupResolutionHarness() {
|
||||
})
|
||||
Eventually(func() bool { return imgCache.Available(rctx) }).Should(BeTrue())
|
||||
|
||||
rsvc = artwork.NewService(rds, imgCache, rstore, ffm)
|
||||
rsvc = artwork.NewArtwork(rds, imgCache, rstore, ffm)
|
||||
rworker = artwork.NewWorker(rds, rstore, agents.GetAgents(rds, nil), ffm, events.NoopBroker(), imgCache)
|
||||
}
|
||||
|
||||
|
||||
@ -34,9 +34,9 @@ func NewImageStore(rootDir string) *ImageStore {
|
||||
return &ImageStore{root: rootDir}
|
||||
}
|
||||
|
||||
// ProvideImageStore roots the store in its own subtree under the data folder, so
|
||||
// GetImageStore roots the store in its own subtree under the data folder, so
|
||||
// Prune's recursive sweep never reaches the per-entity upload folders next to it.
|
||||
func ProvideImageStore() *ImageStore {
|
||||
func GetImageStore() *ImageStore {
|
||||
return NewImageStore(filepath.Join(conf.Server.DataFolder.String(), consts.ArtworkFolder, "store"))
|
||||
}
|
||||
|
||||
|
||||
@ -5,9 +5,9 @@ import (
|
||||
)
|
||||
|
||||
var Set = wire.NewSet(
|
||||
NewService,
|
||||
NewArtwork,
|
||||
GetImageCache,
|
||||
NewWorker,
|
||||
ProvideImageStore,
|
||||
GetImageStore,
|
||||
NewUploader,
|
||||
)
|
||||
|
||||
@ -30,7 +30,7 @@ import (
|
||||
type Router struct {
|
||||
http.Handler
|
||||
ds model.DataStore
|
||||
artwork artwork.Service
|
||||
artwork artwork.Artwork
|
||||
streamer stream.MediaStreamer
|
||||
transcodeDecider stream.TranscodeDecider
|
||||
players core.Players
|
||||
@ -46,7 +46,7 @@ type Router struct {
|
||||
serverIDVal string
|
||||
}
|
||||
|
||||
func New(ds model.DataStore, artwork artwork.Service, streamer stream.MediaStreamer,
|
||||
func New(ds model.DataStore, artwork artwork.Artwork, streamer stream.MediaStreamer,
|
||||
transcodeDecider stream.TranscodeDecider, players core.Players,
|
||||
scrobbler scrobbler.PlayTracker, playlists playlists.Playlists, provider external.Provider,
|
||||
sonicSvc sonic.Engine, lyricsSvc lyrics.Lyrics, broker events.Broker) *Router {
|
||||
|
||||
@ -419,4 +419,4 @@ func (s *spyArtwork) GetOrPlaceholder(c context.Context, id string, _ int, _ boo
|
||||
return &artwork.Image{ReadCloser: io.NopCloser(bytes.NewReader(d))}, nil
|
||||
}
|
||||
|
||||
var _ artwork.Service = &spyArtwork{}
|
||||
var _ artwork.Artwork = &spyArtwork{}
|
||||
|
||||
@ -29,7 +29,7 @@ import (
|
||||
)
|
||||
|
||||
type fakeArtwork struct {
|
||||
artwork.Service
|
||||
artwork.Artwork
|
||||
recvId string
|
||||
recvCtx context.Context
|
||||
data []byte
|
||||
|
||||
@ -34,7 +34,7 @@ var _ = Describe("decodeArtworkID", func() {
|
||||
})
|
||||
|
||||
type fakeArtwork struct {
|
||||
artwork.Service
|
||||
artwork.Artwork
|
||||
img *artwork.Image
|
||||
err error
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ import (
|
||||
|
||||
type Router struct {
|
||||
http.Handler
|
||||
artwork artwork.Service
|
||||
artwork artwork.Artwork
|
||||
streamer stream.MediaStreamer
|
||||
archiver core.Archiver
|
||||
share core.Share
|
||||
@ -26,7 +26,7 @@ type Router struct {
|
||||
ds model.DataStore
|
||||
}
|
||||
|
||||
func New(ds model.DataStore, artwork artwork.Service, streamer stream.MediaStreamer, share core.Share, archiver core.Archiver) *Router {
|
||||
func New(ds model.DataStore, artwork artwork.Artwork, streamer stream.MediaStreamer, share core.Share, archiver core.Archiver) *Router {
|
||||
p := &Router{ds: ds, artwork: artwork, streamer: streamer, share: share, archiver: archiver}
|
||||
shareRoot := path.Join(conf.Server.BasePath, consts.URLPathPublic)
|
||||
p.assetsHandler = http.StripPrefix(shareRoot, http.FileServer(http.FS(ui.BuildAssets())))
|
||||
|
||||
@ -40,7 +40,7 @@ type handlerRaw = func(http.ResponseWriter, *http.Request) (*responses.Subsonic,
|
||||
type Router struct {
|
||||
http.Handler
|
||||
ds model.DataStore
|
||||
artwork artwork.Service
|
||||
artwork artwork.Artwork
|
||||
streamer stream.MediaStreamer
|
||||
archiver core.Archiver
|
||||
players core.Players
|
||||
@ -57,7 +57,7 @@ type Router struct {
|
||||
sonic *sonicsvc.Sonic
|
||||
}
|
||||
|
||||
func New(ds model.DataStore, artwork artwork.Service, streamer stream.MediaStreamer, archiver core.Archiver,
|
||||
func New(ds model.DataStore, artwork artwork.Artwork, streamer stream.MediaStreamer, archiver core.Archiver,
|
||||
players core.Players, provider external.Provider, scanner model.Scanner, broker events.Broker,
|
||||
playlists playlistsvc.Playlists, scrobbler scrobbler.PlayTracker, share core.Share, playback playback.PlaybackServer,
|
||||
metrics metrics.Metrics, lyrics lyricssvc.Lyrics, transcodeDecision stream.TranscodeDecider,
|
||||
|
||||
@ -308,7 +308,7 @@ func parseJSONResponse(w *httptest.ResponseRecorder) *responses.Subsonic {
|
||||
|
||||
// --- Noop stub implementations for Router dependencies ---
|
||||
|
||||
// noopArtwork implements artwork.Service
|
||||
// noopArtwork implements artwork.Artwork
|
||||
type noopArtwork struct{}
|
||||
|
||||
func (n noopArtwork) Get(context.Context, model.ArtworkID, int, bool) (*artwork.Image, error) {
|
||||
@ -359,7 +359,7 @@ func (n noopProvider) TopSongs(context.Context, string, int) (model.MediaFiles,
|
||||
|
||||
// Compile-time interface checks
|
||||
var (
|
||||
_ artwork.Service = noopArtwork{}
|
||||
_ artwork.Artwork = noopArtwork{}
|
||||
_ core.Archiver = noopArchiver{}
|
||||
_ external.Provider = noopProvider{}
|
||||
)
|
||||
|
||||
@ -45,12 +45,12 @@ import (
|
||||
|
||||
// The artwork serving path streams folder-backed originals via os.Open, which a fake FS cannot
|
||||
// back, so this suite scans a small REAL on-disk library and drives the real acquisition worker
|
||||
// and artwork.Service through the Subsonic and public image handlers.
|
||||
// and artwork.Artwork through the Subsonic and public image handlers.
|
||||
var _ = Describe("Artwork Serving", Ordered, func() {
|
||||
var (
|
||||
artRouter *subsonic.Router
|
||||
pubRouter *public.Router
|
||||
artSvc artwork.Service
|
||||
artSvc artwork.Artwork
|
||||
worker *artwork.Worker
|
||||
artfulID string
|
||||
artlessID string
|
||||
@ -134,7 +134,7 @@ var _ = Describe("Artwork Serving", Ordered, func() {
|
||||
store := artwork.NewImageStore(GinkgoT().TempDir())
|
||||
imgCache := newDummyImageCache(ctx)
|
||||
ffm := harness.NoopFFmpeg{}
|
||||
artSvc = artwork.NewService(ds, imgCache, store, ffm)
|
||||
artSvc = artwork.NewArtwork(ds, imgCache, store, ffm)
|
||||
worker = artwork.NewWorker(ds, store, agents.GetAgents(ds, nil), ffm, events.NoopBroker(), imgCache)
|
||||
|
||||
artRouter = buildArtworkRouter(artSvc)
|
||||
@ -233,8 +233,8 @@ var _ = Describe("Artwork Serving", Ordered, func() {
|
||||
})
|
||||
})
|
||||
|
||||
// buildArtworkRouter mirrors setupTestDB's Subsonic wiring but with the real artwork.Service.
|
||||
func buildArtworkRouter(art artwork.Service) *subsonic.Router {
|
||||
// buildArtworkRouter mirrors setupTestDB's Subsonic wiring but with the real artwork.Artwork.
|
||||
func buildArtworkRouter(art artwork.Artwork) *subsonic.Router {
|
||||
decider := stream.NewTranscodeDecider(ds, harness.NoopFFmpeg{})
|
||||
s := scanner.New(ctx, ds, events.NoopBroker(),
|
||||
playlists.NewPlaylists(ds, artwork.NewUploader(ds)), metrics.NewNoopInstance())
|
||||
@ -291,7 +291,7 @@ func readArtworkFixture(name string) []byte {
|
||||
return data
|
||||
}
|
||||
|
||||
// newDummyImageCache backs the artwork.Service's resize cache. size=0 requests stream originals
|
||||
// newDummyImageCache backs the artwork.Artwork's resize cache. size=0 requests stream originals
|
||||
// and never invoke the reader, so it only needs to satisfy the constructor; resize behavior is
|
||||
// covered by the artwork package's own suites.
|
||||
func newDummyImageCache(ctx context.Context) cache.FileCache {
|
||||
|
||||
@ -248,7 +248,7 @@ var _ = Describe("MediaRetrievalController", func() {
|
||||
})
|
||||
|
||||
type fakeArtwork struct {
|
||||
artwork.Service
|
||||
artwork.Artwork
|
||||
data string
|
||||
hash string
|
||||
lastUpdated time.Time
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user