diff --git a/cmd/root.go b/cmd/root.go index f6ea22a0d..e0290f688 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -10,6 +10,7 @@ import ( "github.com/navidrome/navidrome/consts" "github.com/navidrome/navidrome/db" "github.com/navidrome/navidrome/log" + "github.com/navidrome/navidrome/scheduler" "github.com/oklog/run" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -121,10 +122,10 @@ func startSignaler() (func() error, func(err error)) { func schedulePeriodicScan(schedule string) { scanner := GetScanner() - scheduler := GetScheduler() + schedulerInstance := scheduler.GetInstance() log.Info("Scheduling periodic scan", "schedule", schedule) - err := scheduler.Add(schedule, func() { + err := schedulerInstance.Add(schedule, func() { _ = scanner.RescanAll(context.Background(), false) }) if err != nil { @@ -140,11 +141,11 @@ func schedulePeriodicScan(schedule string) { func startScheduler() (func() error, func(err error)) { log.Info("Starting scheduler") - scheduler := GetScheduler() + schedulerInstance := scheduler.GetInstance() ctx, cancel := context.WithCancel(context.Background()) return func() error { - scheduler.Run(ctx) + schedulerInstance.Run(ctx) return nil }, func(err error) { diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index a46934ad7..c8ebe94d2 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -13,7 +13,6 @@ import ( "github.com/navidrome/navidrome/core/transcoder" "github.com/navidrome/navidrome/persistence" "github.com/navidrome/navidrome/scanner" - "github.com/navidrome/navidrome/scheduler" "github.com/navidrome/navidrome/server" "github.com/navidrome/navidrome/server/events" "github.com/navidrome/navidrome/server/nativeapi" @@ -31,7 +30,7 @@ func CreateServer(musicFolder string) *server.Server { func CreateNativeAPIRouter() *nativeapi.Router { dataStore := persistence.New() - broker := GetBroker() + broker := events.GetBroker() share := core.NewShare(dataStore) router := nativeapi.New(dataStore, broker, share) return router @@ -48,8 +47,8 @@ func CreateSubsonicAPIRouter() *subsonic.Router { players := core.NewPlayers(dataStore) externalMetadata := core.NewExternalMetadata(dataStore) scanner := GetScanner() - broker := GetBroker() - scrobblerScrobbler := scrobbler.New(dataStore) + broker := events.GetBroker() + scrobblerScrobbler := scrobbler.GetInstance(dataStore) router := subsonic.New(dataStore, artwork, mediaStreamer, archiver, players, externalMetadata, scanner, broker, scrobblerScrobbler) return router } @@ -65,24 +64,14 @@ func createScanner() scanner.Scanner { artworkCache := core.GetImageCache() artwork := core.NewArtwork(dataStore, artworkCache) cacheWarmer := core.NewCacheWarmer(artwork, artworkCache) - broker := GetBroker() + broker := events.GetBroker() scannerScanner := scanner.New(dataStore, cacheWarmer, broker) return scannerScanner } -func createBroker() events.Broker { - broker := events.NewBroker() - return broker -} - -func createScheduler() scheduler.Scheduler { - schedulerScheduler := scheduler.New() - return schedulerScheduler -} - // wire_injectors.go: -var allProviders = wire.NewSet(core.Set, subsonic.New, nativeapi.New, persistence.New, lastfm.NewRouter, GetBroker) +var allProviders = wire.NewSet(core.Set, subsonic.New, nativeapi.New, persistence.New, lastfm.NewRouter, events.GetBroker) // Scanner must be a Singleton var ( @@ -96,29 +85,3 @@ func GetScanner() scanner.Scanner { }) return scannerInstance } - -// Broker must be a Singleton -var ( - onceBroker sync.Once - brokerInstance events.Broker -) - -func GetBroker() events.Broker { - onceBroker.Do(func() { - brokerInstance = createBroker() - }) - return brokerInstance -} - -// Scheduler must be a Singleton -var ( - onceScheduler sync.Once - schedulerInstance scheduler.Scheduler -) - -func GetScheduler() scheduler.Scheduler { - onceScheduler.Do(func() { - schedulerInstance = createScheduler() - }) - return schedulerInstance -} diff --git a/cmd/wire_injectors.go b/cmd/wire_injectors.go index 95e9c913b..4c906de50 100644 --- a/cmd/wire_injectors.go +++ b/cmd/wire_injectors.go @@ -5,14 +5,14 @@ package cmd import ( "sync" + "github.com/navidrome/navidrome/server/events" + "github.com/google/wire" "github.com/navidrome/navidrome/core" "github.com/navidrome/navidrome/core/agents/lastfm" "github.com/navidrome/navidrome/persistence" "github.com/navidrome/navidrome/scanner" - "github.com/navidrome/navidrome/scheduler" "github.com/navidrome/navidrome/server" - "github.com/navidrome/navidrome/server/events" "github.com/navidrome/navidrome/server/nativeapi" "github.com/navidrome/navidrome/server/subsonic" ) @@ -23,7 +23,7 @@ var allProviders = wire.NewSet( nativeapi.New, persistence.New, lastfm.NewRouter, - GetBroker, + events.GetBroker, ) func CreateServer(musicFolder string) *server.Server { @@ -71,41 +71,3 @@ func createScanner() scanner.Scanner { scanner.New, )) } - -// Broker must be a Singleton -var ( - onceBroker sync.Once - brokerInstance events.Broker -) - -func GetBroker() events.Broker { - onceBroker.Do(func() { - brokerInstance = createBroker() - }) - return brokerInstance -} - -func createBroker() events.Broker { - panic(wire.Build( - events.NewBroker, - )) -} - -// Scheduler must be a Singleton -var ( - onceScheduler sync.Once - schedulerInstance scheduler.Scheduler -) - -func GetScheduler() scheduler.Scheduler { - onceScheduler.Do(func() { - schedulerInstance = createScheduler() - }) - return schedulerInstance -} - -func createScheduler() scheduler.Scheduler { - panic(wire.Build( - scheduler.New, - )) -} diff --git a/core/scrobbler/scrobbler.go b/core/scrobbler/scrobbler.go index f9890abd1..f2e281f86 100644 --- a/core/scrobbler/scrobbler.go +++ b/core/scrobbler/scrobbler.go @@ -32,7 +32,7 @@ type scrobbler struct { playMap *ttlcache.Cache } -func New(ds model.DataStore) Scrobbler { +func GetInstance(ds model.DataStore) Scrobbler { instance := singleton.Get(scrobbler{}, func() interface{} { m := ttlcache.NewCache() m.SkipTTLExtensionOnHit(true) diff --git a/core/wire_providers.go b/core/wire_providers.go index 1bda91f01..0f0a3f2bc 100644 --- a/core/wire_providers.go +++ b/core/wire_providers.go @@ -16,6 +16,6 @@ var Set = wire.NewSet( NewCacheWarmer, NewPlayers, transcoder.New, - scrobbler.New, + scrobbler.GetInstance, NewShare, ) diff --git a/scheduler/scheduler.go b/scheduler/scheduler.go index bfc0e81e8..ff4a3b11a 100644 --- a/scheduler/scheduler.go +++ b/scheduler/scheduler.go @@ -3,6 +3,7 @@ package scheduler import ( "context" + "github.com/navidrome/navidrome/utils/singleton" "github.com/robfig/cron/v3" ) @@ -11,11 +12,14 @@ type Scheduler interface { Add(crontab string, cmd func()) error } -func New() Scheduler { - c := cron.New(cron.WithLogger(&logger{})) - return &scheduler{ - c: c, - } +func GetInstance() Scheduler { + instance := singleton.Get(&scheduler{}, func() interface{} { + c := cron.New(cron.WithLogger(&logger{})) + return &scheduler{ + c: c, + } + }) + return instance.(*scheduler) } type scheduler struct { diff --git a/server/events/sse.go b/server/events/sse.go index a9f808b0b..dc09c2efd 100644 --- a/server/events/sse.go +++ b/server/events/sse.go @@ -10,6 +10,8 @@ import ( "sync/atomic" "time" + "github.com/navidrome/navidrome/utils/singleton" + "code.cloudfoundry.org/go-diodes" "github.com/google/uuid" "github.com/navidrome/navidrome/consts" @@ -69,18 +71,21 @@ type broker struct { unsubscribing clientsChan } -func NewBroker() Broker { - // Instantiate a broker - broker := &broker{ - publish: make(messageChan, 100), - subscribing: make(clientsChan, 1), - unsubscribing: make(clientsChan, 1), - } +func GetBroker() Broker { + instance := singleton.Get(&broker{}, func() interface{} { + // Instantiate a broker + broker := &broker{ + publish: make(messageChan, 100), + subscribing: make(clientsChan, 1), + unsubscribing: make(clientsChan, 1), + } - // Set it running - listening and broadcasting events - go broker.listen() + // Set it running - listening and broadcasting events + go broker.listen() + return broker + }) - return broker + return instance.(*broker) } func (b *broker) SendMessage(ctx context.Context, evt Event) {