Commit bf90695
committed
Widen uncovered-release candidate set to rotation ∪ recently played (BS#1877 amendment)
The search handoff offered only active rotation (~300 releases), but most of what DJs actually play — and what listeners see — is not current rotation. The candidate set is now active rotation ∪ recently played linked albums, keeping the wire schema, exact-match ceiling, and ADR 0013 architecture unchanged.
- New plays.ts: fetchRecentPlays(lookbackDays) windows flowsheet (entry_type='track', album_id linked, canonical pair via the artists join); fetchAllPlayedAlbums() sources the album_plays MV for the one-time --backfill drain (37,421 albums, play-count desc, deliberately no SQL LIMIT — a LIMIT would silently stall the drain against the handed-off anti-join).
- orchestrate.ts: single mode-blind fetchPlayCandidates injection; rotation-first concat + first-wins dedup; one cap (UNCOVERED_MAX_RELEASES_PER_RUN) post-anti-join and pre-DRY_RUN, capped_out computed at the cap site; the capped list feeds render/write/publish/recordHandoffs alike; rotation-lane guards stay hard throws in steady state and demote to log + Sentry captureError under --backfill; zero-plays escalates without throwing; locked DRY_RUN report widened with backfill, recent_play_rows, candidate_rows, capped_out.
- Dockerfile: CMD → ENTRYPOINT + empty CMD so docker-level --backfill passes through; this deliberately relocates the default OUTPUT_PATH to the WORKDIR (documented).
- Backfill pacing: single-path whole-file publish + publish-once markers means at most one --backfill invocation per consumer cycle until research-data#16 walks the snapshot branch history; requirement relayed on that ticket (WXYC/research-data#16 (comment)).
- Docs: README rewrite (modes, cap semantics, pacing, guards, locked report), ADR 0013 line-57 sizing (credential-conditional), env-vars, ops-cron-scheduling, package description, workspace CLAUDE.md row, stale header sweeps.
- Tests: unit coverage for both arms, options parsing, cap/dedup/guard behavior (report matched on its unique line prefix, not a shared token); integration cases for both arms with sql.unsafe MV refresh and fixture-scoped scoped* helpers.
Steady-state cost after PUBLISH + RESEARCH_DATA_WRITE_TOKEN are provisioned: ~75 new albums/week ≈ 325 searches/month. Measured: play aggregate ~174 ms unindexed; anti-join 13–25 ms at the full 37,421-id cardinality.
Code-review fixes folded in: the backfill and pull-from-container recipes now bind-mount the output directory instead of promising a docker cp that --rm makes impossible (with the credential unprovisioned that file is the run's only artifact, so the old recipe silently lost the batch); the empty-snapshot publish skip from the parent commit is re-keyed onto the capped list, which is what actually gets rendered, written, and published; and plays.ts cites the migration that creates flowsheet_track_add_time_idx rather than a schema.ts line range that had already rotted onto an unrelated block comment.
Renumbers this PR's references to the marker migration from 0146 to 0156, matching the schema PR beneath it: main landed its own 0146 (library-delete-denylist, BS#2112) while this stack sat open. Touched job.ts's header comment (resolved against this branch's widened prose, which is kept) and the job's CLAUDE.md registration row. The surviving "migration 0146" in jobs/library-etl/README.md is correct as-is — it refers to main's denylist migration, not this one.1 parent f0b2c30 commit bf90695
15 files changed
Lines changed: 1055 additions & 104 deletions
File tree
- docs
- adr
- jobs/uncovered-release-list
- tests
- integration
- unit/jobs/uncovered-release-list
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
57 | | - | |
| 57 | + | |
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| |||
69 | 69 | | |
70 | 70 | | |
71 | 71 | | |
| 72 | + | |
| 73 | + | |
72 | 74 | | |
73 | 75 | | |
74 | 76 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
372 | 372 | | |
373 | 373 | | |
374 | 374 | | |
375 | | - | |
| 375 | + | |
376 | 376 | | |
377 | | - | |
| 377 | + | |
378 | 378 | | |
379 | | - | |
380 | | - | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
381 | 383 | | |
382 | 384 | | |
383 | 385 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
54 | | - | |
| 54 | + | |
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| |||
0 commit comments