feat(scrobble): add MaybeEnqueue with idempotent insert + threshold gate
Bridges closed play_events to the scrobble_queue: loads the event, applies the Qualifies() threshold, checks user LB config (enabled + token), and inserts via ON CONFLICT DO NOTHING for idempotency. Best-effort — callers (playevents.Writer hooks, Task 8) will log and swallow errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package scrobble
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
|
||||
)
|
||||
|
||||
// MaybeEnqueue inserts a scrobble_queue row for the given play_event if:
|
||||
// 1. The user has listenbrainz_enabled = true with a non-empty token.
|
||||
// 2. The play_event passes Qualifies().
|
||||
//
|
||||
// Idempotent via UNIQUE(play_event_id) — re-runs are no-ops.
|
||||
//
|
||||
// Best-effort: callers (the playevents.Writer hooks) should log returned
|
||||
// errors but not propagate them, since scrobble delivery is enrichment
|
||||
// and must not block the canonical play history.
|
||||
func MaybeEnqueue(ctx context.Context, q *dbq.Queries, playEventID pgtype.UUID) error {
|
||||
pe, err := q.GetPlayEventByID(ctx, playEventID)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
// Only closed events qualify (DurationPlayedMs/CompletionRatio populated).
|
||||
if pe.DurationPlayedMs == nil || pe.CompletionRatio == nil {
|
||||
return nil
|
||||
}
|
||||
if !Qualifies(int(*pe.DurationPlayedMs), *pe.CompletionRatio) {
|
||||
return nil
|
||||
}
|
||||
cfg, err := q.GetListenBrainzConfig(ctx, pe.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !cfg.ListenbrainzEnabled || cfg.ListenbrainzToken == nil || *cfg.ListenbrainzToken == "" {
|
||||
return nil
|
||||
}
|
||||
_, err = q.EnqueueScrobble(ctx, dbq.EnqueueScrobbleParams{
|
||||
UserID: pe.UserID,
|
||||
PlayEventID: pe.ID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user