Reduce retention in CacheWarmer

This commit is contained in:
Deluan 2022-12-28 13:03:41 -05:00 committed by Deluan Quintão
parent 61e5523457
commit 14032a524b

View File

@ -4,10 +4,13 @@ import (
"context" "context"
"fmt" "fmt"
"io" "io"
"sync"
"time"
"github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/model/request"
"github.com/navidrome/navidrome/utils/pl" "github.com/navidrome/navidrome/utils/pl"
) )
@ -22,24 +25,63 @@ func NewCacheWarmer(artwork Artwork) CacheWarmer {
} }
a := &cacheWarmer{ a := &cacheWarmer{
artwork: artwork, artwork: artwork,
input: make(chan string), wakeSignal: make(chan struct{}, 1),
} }
go a.run(context.TODO())
// Create a context with a fake admin user, to be able to pre-cache Playlist CoverArts
ctx := request.WithUser(context.TODO(), model.User{IsAdmin: true})
go a.run(ctx)
return a return a
} }
type cacheWarmer struct { type cacheWarmer struct {
artwork Artwork artwork Artwork
input chan string buffer []string
mutex sync.Mutex
wakeSignal chan struct{}
} }
func (a *cacheWarmer) PreCache(artID model.ArtworkID) { func (a *cacheWarmer) PreCache(artID model.ArtworkID) {
a.input <- artID.String() a.mutex.Lock()
defer a.mutex.Unlock()
a.buffer = append(a.buffer, artID.String())
a.sendWakeSignal()
}
func (a *cacheWarmer) sendWakeSignal() {
// Don't block if the previous signal was not read yet
select {
case a.wakeSignal <- struct{}{}:
default:
}
} }
func (a *cacheWarmer) run(ctx context.Context) { func (a *cacheWarmer) run(ctx context.Context) {
errs := pl.Sink(ctx, 2, a.input, a.doCacheImage) for {
time.AfterFunc(5*time.Second, func() {
a.sendWakeSignal()
})
<-a.wakeSignal
a.mutex.Lock()
var batch []string
if len(a.buffer) > 0 {
batch = a.buffer
a.buffer = nil
}
a.mutex.Unlock()
if len(batch) > 0 {
a.processBatch(ctx, batch)
}
}
}
func (a *cacheWarmer) processBatch(ctx context.Context, batch []string) {
log.Trace(ctx, "PreCaching a new batch of artwork", "batchSize", len(batch))
input := pl.FromSlice(ctx, batch)
errs := pl.Sink(ctx, 2, input, a.doCacheImage)
for err := range errs { for err := range errs {
log.Warn(ctx, "Error warming cache", err) log.Warn(ctx, "Error warming cache", err)
} }