radieo/ingest
Pierre-Olivier Mercier 7e0f08b863 Milestone 5: MusicBrainz MBID canonicalizer
Give tracks a source-agnostic identity so the same song from different
sources no longer replays in a loop.

- Canonicalizer resolves (artist, title) to a MusicBrainz recording MBID
  (no API key; ~1 req/s, descriptive User-Agent, best-effort). Hits and
  confirmed misses are cached in SQLite; transient errors are not.
- Track.key becomes mbid:<id> when resolved, else a normalized
  name:<artist>|<title> fallback — still source-agnostic.
- Scheduler now owns the authoritative anti-repeat on the canonical key,
  canonicalizing the drawn track with a bounded retry; providers keep a
  cheap recent-locator filter to limit retries.
- db: canonical_cache table, history.locator column with migration for
  existing databases, recent_locators().
- Canonicalization can be turned off via RADIEO_CANONICAL_ENABLED=0.

Verified: MBID hit/cache/miss, cross-source key collapse, scheduler
dodging a recent play, schema migration, and full stack (Navidrome +
yt-dlp) with zero Python tracebacks and a valid 192 kbps MP3 stream.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 18:46:30 +08:00
..
radieo Milestone 5: MusicBrainz MBID canonicalizer 2026-07-02 18:46:30 +08:00
Dockerfile Milestone 3: Navidrome (OpenSubsonic) playback provider 2026-07-02 17:57:38 +08:00
requirements.txt Milestone 4: yt-dlp provider and weighted source scheduler 2026-07-02 17:58:24 +08:00