mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-13 04:47:17 +02:00
feat(artwork): read a single queue row by item
The explain CLI must report whether an item is queued, at what priority and when it retries; the queue repository could only be drained in eligibility batches, which cannot see a row that is still backing off.
This commit is contained in:
parent
e3c78a9cb1
commit
5ba8a9fcb5
4 changed files with 41 additions and 0 deletions
|
|
@ -119,6 +119,8 @@ type ArtworkRepository interface {
|
|||
}
|
||||
|
||||
type ArtworkQueueRepository interface {
|
||||
// Get returns the pending row for an item, or ErrNotFound when it is not queued.
|
||||
Get(kind Kind, id, imageType string) (*ArtworkQueueItem, error)
|
||||
// Enqueue upserts; an existing row keeps the higher priority and has its retry_at reset.
|
||||
Enqueue(items ...ArtworkQueueItem) error
|
||||
// EnqueuePreservingBackoff upserts like Enqueue but preserves an existing row's retry_at, so a
|
||||
|
|
|
|||
|
|
@ -31,6 +31,16 @@ func NewArtworkQueueRepository(ctx context.Context, db dbx.Builder) model.Artwor
|
|||
return r
|
||||
}
|
||||
|
||||
func (r *artworkQueueRepository) Get(kind model.Kind, id, imageType string) (*model.ArtworkQueueItem, error) {
|
||||
var res model.ArtworkQueueItem
|
||||
err := r.queryOne(Select("*").From(r.tableName).
|
||||
Where(Eq{"item_kind": kind.Prefix(), "item_id": id, "image_type": imageType}), &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// Enqueue also resets enqueued_at, so a fresh request does not inherit an old row's spent retry budget.
|
||||
func (r *artworkQueueRepository) Enqueue(items ...model.ArtworkQueueItem) error {
|
||||
return r.enqueue(`ON CONFLICT (item_kind, item_id, image_type) DO UPDATE SET
|
||||
|
|
|
|||
|
|
@ -54,6 +54,22 @@ var _ = Describe("ArtworkQueueRepository", func() {
|
|||
Expect(got[0].ItemID).To(Equal("high"))
|
||||
})
|
||||
|
||||
It("Get returns a queued row, including one still backing off", func() {
|
||||
Expect(repo.Enqueue(item("ar", "g1", model.ArtworkPriorityScan))).To(Succeed())
|
||||
backOff("ar", "g1", time.Now().Add(time.Hour))
|
||||
|
||||
got, err := repo.Get(model.KindArtistArtwork, "g1", model.ImageTypePrimary)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(got.Priority).To(Equal(model.ArtworkPriorityScan))
|
||||
Expect(got.Attempts).To(Equal(1))
|
||||
Expect(got.RetryAt).To(BeTemporally(">", time.Now()))
|
||||
})
|
||||
|
||||
It("Get reports ErrNotFound when the item is not queued", func() {
|
||||
_, err := repo.Get(model.KindArtistArtwork, "nope", model.ImageTypePrimary)
|
||||
Expect(err).To(MatchError(model.ErrNotFound))
|
||||
})
|
||||
|
||||
It("keeps the higher priority on duplicate enqueue", func() {
|
||||
Expect(repo.Enqueue(item("al", "a1", model.ArtworkPriorityBump))).To(Succeed())
|
||||
Expect(repo.Enqueue(item("al", "a1", model.ArtworkPriorityBackfill))).To(Succeed())
|
||||
|
|
|
|||
|
|
@ -25,6 +25,19 @@ func CreateMockArtworkQueueRepo() *MockArtworkQueueRepo {
|
|||
return &MockArtworkQueueRepo{Data: map[string]model.ArtworkQueueItem{}}
|
||||
}
|
||||
|
||||
func (m *MockArtworkQueueRepo) Get(kind model.Kind, id, imageType string) (*model.ArtworkQueueItem, error) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if m.Err != nil {
|
||||
return nil, m.Err
|
||||
}
|
||||
it, ok := m.Data[iaKey(kind.Prefix(), id, imageType)]
|
||||
if !ok {
|
||||
return nil, model.ErrNotFound
|
||||
}
|
||||
return &it, nil
|
||||
}
|
||||
|
||||
func (m *MockArtworkQueueRepo) Enqueue(items ...model.ArtworkQueueItem) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue