Repository navigation
refactor(core): provider-neutral external identities; Deezer-free core workflows - #39
Merged
Merged
Conversation
…re workflows (final cleanup) Core no longer carries Deezer-specific identity fields, naming, or behavioral assumptions. One focused cleanup PR (no SDK redesign, no new providers, no versioning). Domain model (provider-neutral identity): - Artist.spotify_id -> Artist.external_id; Album/Track.deezer_id -> external_id; DownloadJob.album_spotify_id -> album_external_id. Values are OPAQUE provider identities; core never parses/int()s them. - Startup migration renames the columns on existing databases (SQLite RENAME COLUMN; data, NOT NULL/unique constraints and indexes preserved; fresh DBs get the new names via create_all). - SDK TrackRef gains provider-neutral external_id; deezer_id remains as a documented deprecated alias (no plugin reads it). Core workflows (artist search/import/sync/download/import/metadata): - _sync_artist_discography_background / _start_bounded_artist_sync / api_add_artist / api_artist_sync / folder + bulk import / periodic scheduler: external identity is an opaque string end-to-end; no int(), no isdigit() heuristic, no "resolve Deezer ID". - Indexing/pruning/ISRC lookups/dedup use the external id generically; MetadataService docstrings no longer name any provider authoritative or interpret provider ids; the deezer plugin owns conversion/validation and declines foreign ids gracefully (chain moves on, no crash). - Legacy wire compatibility isolated + documented: /set-external-id accepts the old /set-deezer-id path and body key; import accepts deezer_id as an alias of external_id; the import-candidate suggestion is emitted under suggested_external_id (suggested_deezer kept as an alias) and the frontend was updated to the neutral keys. - Manual-match user-pasted Deezer URLs and the provider-URL help text are user-facing input handling; the lookups they trigger go through the capability chain (annotated). Tests: - tests/architecture/test_provider_neutral_identity.py (new): fake non-integer (fake-artist-123) and colon-prefixed (artist:abc:def) identities flow through search/discography; the Deezer plugin converts ids inside the plugin and declines foreign ones; removing the provider leaves the chain working, and zero providers raises CapabilityUnavailable (no hidden Deezer fallback). - Background app-context regression (real _process_track_job on a ThreadPoolExecutor worker with a settings-reading provider) unchanged and green; structural test still covers all three protected entry points. Docs: docs/architecture.md gained a provider-neutral identity section and no longer calls any provider authoritative; wayfinder records the change. Verified: architecture suite 22/22, smoke PASSED, fnack-plugins parity OK (bundled plugins untouched, byte-identical). Live container: DB migrated in place, Arctic Monkeys added + discography synced (32 albums/150 tracks) and 'Do I Wanna Know?' downloaded/verified through the queue worker.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
One focused cleanup PR (per the provider-neutral-core cleanup brief). No SDK redesign, no new providers, no capability changes, no versioning.
What changed
Provider-neutral identity (domain model + migration)
Artist.spotify_id→Artist.external_id,Album.deezer_id/Track.deezer_id→external_id,DownloadJob.album_spotify_id→album_external_id. Values are opaque provider identities; core never parses orint()s them.RENAME COLUMN; data, NOT NULL/unique constraints and indexes preserved — verified on the live DB). Fresh DBs get the new names viacreate_all.TrackRefgains provider-neutralexternal_id;deezer_idstays as a documented deprecated alias (no plugin reads it).Deezer-specific logic removed from core workflows
int(deezer_artist_id), noisdigit()heuristics, no "resolve Deezer ID".MetadataServicedocstrings no longer name any provider authoritative.fnack.deezer-batch(itint()s its own ids and declines foreign ids gracefully — the chain moves on)./set-external-idalso answers the old/set-deezer-idpath/body key; import acceptsdeezer_idas an alias ofexternal_id; candidate suggestions now emitsuggested_external_id(suggested_deezerkept as alias) and the frontend was updated to the neutral keys.Tests
tests/architecture/test_provider_neutral_identity.py(Tests A–D): fake non-integer (fake-artist-123) and colon-prefixed (artist:abc:def) identities flow through search/discography; the Deezer plugin converts ids inside the plugin and declines foreign ones; provider removal leaves the chain working; zero providers →CapabilityUnavailable, no hidden Deezer fallback._process_track_jobon a ThreadPoolExecutor worker with a settings-reading provider) unchanged + green; the structural test still covers all three protected entry points.Live verification
Container rebuilt from this code: the live DB migrated in place; Arctic Monkeys was added via search → discography synced (32 albums / 150 tracks) through the opaque-external-id path → "Do I Wanna Know?" downloaded, verified, and accepted through the queue worker (ISRC lookup + settings read from the worker thread).
Remaining provider mentions in core (all classified)
deezer_iddeprecated alias +TrackRefcomment examples.