diff --git a/internal/library/scanrun.go b/internal/library/scanrun.go index e53612ba..d2b72566 100644 --- a/internal/library/scanrun.go +++ b/internal/library/scanrun.go @@ -156,10 +156,16 @@ func RunScan( // Stage 2b: track recording-MBID backfill. Unblocks the ListenBrainz // similarity pipeline (gated on tracks.mbid IS NOT NULL). Log-only - // progress — no scan_runs jsonb column to avoid a schema addition; - // it's idempotent and reruns each scan until every file is healed. + // progress — no scan_runs jsonb column to avoid a schema addition. + // + // Unbounded (-1), unlike the album backfill's 5000 staged cap: this + // is a one-time whole-library heal with no progress UI, and a cap + // just means tracks.mbid stays partially NULL until N future scans + // catch up (re-reading untagged files wastefully each pass). One + // uncapped pass converges; subsequent scans only re-read the + // remaining NULL (genuinely untagged) rows, which is cheap. if cfg.BackfillCap != 0 { - if _, tberr := BackfillTrackMBIDs(ctx, pool, logger, cfg.BackfillCap, nil); tberr != nil { + if _, tberr := BackfillTrackMBIDs(ctx, pool, logger, -1, nil); tberr != nil { captureErr("track_mbid_backfill", tberr) } } diff --git a/internal/similarity/worker.go b/internal/similarity/worker.go index e37cf5be..8ce64ede 100644 --- a/internal/similarity/worker.go +++ b/internal/similarity/worker.go @@ -34,14 +34,16 @@ type Worker struct { } // NewWorker constructs a worker with production defaults: 1h tick, -// batch=5, topK=20. +// batch=25, topK=20. batch is tracks AND artists processed per tick; +// at 25/h a freshly-played library converges in hours, not days, while +// staying well under ListenBrainz rate limits (429s abort the tick). func NewWorker(pool *pgxpool.Pool, client *listenbrainz.Client, logger *slog.Logger) *Worker { return &Worker{ pool: pool, client: client, logger: logger, tick: 1 * time.Hour, - batch: 5, + batch: 25, topK: 20, } }