refactor: better implementation of newRefreshQueue.

- use pointer references in channel
 - actually exits when context is canceled

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan 2024-11-15 19:44:33 +02:00
parent 6c38dc234f
commit 1bf94531fd

View File

@ -43,8 +43,8 @@ type ExternalMetadata interface {
type externalMetadata struct { type externalMetadata struct {
ds model.DataStore ds model.DataStore
ag *agents.Agents ag *agents.Agents
artistQueue refreshQueue[auxArtist] artistQueue refreshQueue[*auxArtist]
albumQueue refreshQueue[auxAlbum] albumQueue refreshQueue[*auxAlbum]
} }
type auxAlbum struct { type auxAlbum struct {
@ -103,7 +103,7 @@ func (e *externalMetadata) UpdateAlbumInfo(ctx context.Context, id string) (*mod
// If info is expired, trigger a populateAlbumInfo in the background // If info is expired, trigger a populateAlbumInfo in the background
if time.Since(updatedAt) > conf.Server.DevAlbumInfoTimeToLive { if time.Since(updatedAt) > conf.Server.DevAlbumInfoTimeToLive {
log.Debug("Found expired cached AlbumInfo, refreshing in the background", "updatedAt", album.ExternalInfoUpdatedAt, "name", album.Name) log.Debug("Found expired cached AlbumInfo, refreshing in the background", "updatedAt", album.ExternalInfoUpdatedAt, "name", album.Name)
e.albumQueue.enqueue(*album) e.albumQueue.enqueue(album)
} }
return &album.Album, nil return &album.Album, nil
@ -206,7 +206,7 @@ func (e *externalMetadata) refreshArtistInfo(ctx context.Context, id string) (*a
// If info is expired, trigger a populateArtistInfo in the background // If info is expired, trigger a populateArtistInfo in the background
if time.Since(updatedAt) > conf.Server.DevArtistInfoTimeToLive { if time.Since(updatedAt) > conf.Server.DevArtistInfoTimeToLive {
log.Debug("Found expired cached ArtistInfo, refreshing in the background", "updatedAt", updatedAt, "name", artist.Name) log.Debug("Found expired cached ArtistInfo, refreshing in the background", "updatedAt", updatedAt, "name", artist.Name)
e.artistQueue.enqueue(*artist) e.artistQueue.enqueue(artist)
} }
return artist, nil return artist, nil
} }
@ -554,25 +554,27 @@ func (e *externalMetadata) loadSimilar(ctx context.Context, artist *auxArtist, c
type refreshQueue[T any] chan<- T type refreshQueue[T any] chan<- T
func newRefreshQueue[T any](ctx context.Context, processFn func(context.Context, *T) error) refreshQueue[T] { func newRefreshQueue[T any](ctx context.Context, processFn func(context.Context, T) error) refreshQueue[T] {
queue := make(chan T, refreshQueueLength) queue := make(chan T, refreshQueueLength)
go func() { go func() {
for { for {
time.Sleep(refreshDelay) select {
case <-ctx.Done():
return
case <-time.After(refreshDelay):
ctx, cancel := context.WithTimeout(ctx, refreshTimeout) ctx, cancel := context.WithTimeout(ctx, refreshTimeout)
select { select {
case item := <-queue: case item := <-queue:
_ = processFn(ctx, &item) _ = processFn(ctx, item)
cancel() cancel()
case <-ctx.Done(): case <-ctx.Done():
cancel() cancel()
break }
} }
} }
}() }()
return queue return queue
} }
func (q *refreshQueue[T]) enqueue(item T) { func (q *refreshQueue[T]) enqueue(item T) {
select { select {
case *q <- item: case *q <- item: