Implement Scrobble buffering/retrying

This commit is contained in:
Deluan
2021-06-24 00:01:05 -04:00
parent fb183e58e9
commit 289da56f64
17 changed files with 513 additions and 96 deletions
+29 -28
View File
@@ -39,9 +39,10 @@ type PlayTracker interface {
}
type playTracker struct {
ds model.DataStore
broker events.Broker
playMap *ttlcache.Cache
ds model.DataStore
broker events.Broker
playMap *ttlcache.Cache
scrobblers map[string]Scrobbler
}
func GetPlayTracker(ds model.DataStore, broker events.Broker) PlayTracker {
@@ -49,7 +50,14 @@ func GetPlayTracker(ds model.DataStore, broker events.Broker) PlayTracker {
m := ttlcache.NewCache()
m.SkipTTLExtensionOnHit(true)
_ = m.SetTTL(nowPlayingExpire)
return &playTracker{ds: ds, playMap: m, broker: broker}
p := &playTracker{ds: ds, playMap: m, broker: broker}
p.scrobblers = make(map[string]Scrobbler)
for name, constructor := range constructors {
s := constructor(ds)
s = NewBufferedScrobbler(ds, s, name)
p.scrobblers[name] = s
}
return p
})
return instance.(*playTracker)
}
@@ -78,15 +86,12 @@ func (p *playTracker) dispatchNowPlaying(ctx context.Context, userId string, tra
return
}
// TODO Parallelize
for name, constructor := range scrobblers {
err := func() error {
s := constructor(p.ds)
if !s.IsAuthorized(ctx, userId) {
return nil
}
log.Debug(ctx, "Sending NowPlaying info", "scrobbler", name, "track", t.Title, "artist", t.Artist)
return s.NowPlaying(ctx, userId, t)
}()
for name, s := range p.scrobblers {
if !s.IsAuthorized(ctx, userId) {
continue
}
log.Debug(ctx, "Sending NowPlaying info", "scrobbler", name, "track", t.Title, "artist", t.Artist)
err := s.NowPlaying(ctx, userId, t)
if err != nil {
log.Error(ctx, "Error sending NowPlayingInfo", "scrobbler", name, "track", t.Title, "artist", t.Artist, err)
return
@@ -161,17 +166,13 @@ func (p *playTracker) incPlay(ctx context.Context, track *model.MediaFile, times
func (p *playTracker) dispatchScrobble(ctx context.Context, t *model.MediaFile, playTime time.Time) error {
u, _ := request.UserFrom(ctx)
scrobbles := []Scrobble{{MediaFile: *t, TimeStamp: playTime}}
// TODO Parallelize
for name, constructor := range scrobblers {
err := func() error {
s := constructor(p.ds)
if !s.IsAuthorized(ctx, u.ID) {
return nil
}
log.Debug(ctx, "Sending Scrobble", "scrobbler", name, "track", t.Title, "artist", t.Artist)
return s.Scrobble(ctx, u.ID, scrobbles)
}()
scrobble := Scrobble{MediaFile: *t, TimeStamp: playTime}
for name, s := range p.scrobblers {
if !s.IsAuthorized(ctx, u.ID) {
continue
}
log.Debug(ctx, "Buffering scrobble", "scrobbler", name, "track", t.Title, "artist", t.Artist)
err := s.Scrobble(ctx, u.ID, scrobble)
if err != nil {
log.Error(ctx, "Error sending Scrobble", "scrobbler", name, "track", t.Title, "artist", t.Artist, err)
return err
@@ -180,14 +181,14 @@ func (p *playTracker) dispatchScrobble(ctx context.Context, t *model.MediaFile,
return nil
}
var scrobblers map[string]Constructor
var constructors map[string]Constructor
func Register(name string, init Constructor) {
if !conf.Server.DevEnableScrobble {
return
}
if scrobblers == nil {
scrobblers = make(map[string]Constructor)
if constructors == nil {
constructors = make(map[string]Constructor)
}
scrobblers[name] = init
constructors[name] = init
}