From 3284af428d15aa883f274d828a733ccec465ad8e Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Thu, 11 Jun 2026 08:33:26 -0700 Subject: [PATCH] Discogs (#848 follow-up): tag collection album IDs for consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Your Albums Discogs collection sync stored bare release_ids while search/discography now store tagged ('r') ones (#848). This didn't cause a live bug — the pool dedups by normalized name, and discogs_release_id is only ever re-fetched (which handles bare via release-first) — but it left the "type travels with the ID" invariant half-applied. Now the collection sync tags its IDs too, so every stored Discogs album ID is uniform and a future ID comparison can't be tripped by mixed forms. Collection items are always releases, so they're tagged 'r'. Test locks the stored value + that a tagged collection ID routes only to /releases (never /masters). --- tests/test_discogs_collection_id_tagging.py | 40 +++++++++++++++++++++ web_server.py | 6 +++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/test_discogs_collection_id_tagging.py diff --git a/tests/test_discogs_collection_id_tagging.py b/tests/test_discogs_collection_id_tagging.py new file mode 100644 index 00000000..a1cdc663 --- /dev/null +++ b/tests/test_discogs_collection_id_tagging.py @@ -0,0 +1,40 @@ +"""#848 follow-up: the Your Albums Discogs collection sync stores album IDs +TAGGED ('r') like search/discography, so every stored Discogs album ID is +uniform and re-fetches route to the correct endpoint (no master/release collision). + +The divergence didn't cause a live bug (the pool dedups by normalized name, and +discogs_release_id is only ever re-fetched — which handles bare too); this locks +in the consistency so a future ID comparison can't be tripped by mixed forms. +""" + +from __future__ import annotations + +import pytest + +from core.discogs_client import _tag_discogs_album_id, _discogs_album_endpoints +from database.music_database import MusicDatabase + + +def test_collection_release_id_is_tagged_and_routes_to_releases_only(tmp_path): + db = MusicDatabase(str(tmp_path / "m.db")) + # Exactly what the Your Albums Discogs sync now passes (collection = releases). + ok = db.upsert_liked_album( + album_name="Some Album", artist_name="Some Artist", + source_service="discogs", + source_id=_tag_discogs_album_id(7361634, "release"), source_id_type="discogs", + profile_id=1, + ) + assert ok + with db._get_connection() as conn: + row = conn.execute( + "SELECT discogs_release_id FROM liked_albums_pool WHERE profile_id = 1" + ).fetchone() + assert row is not None + assert row["discogs_release_id"] == "r7361634" # stored tagged, not bare + # A tagged collection ID routes ONLY to /releases — never /masters — so it + # can't hit the master/release collision #848 fixed. + assert _discogs_album_endpoints("r7361634") == ["/releases/7361634"] + + +def test_tagged_collection_id_never_hits_masters(): + assert "/masters/" not in " ".join(_discogs_album_endpoints(_tag_discogs_album_id(123, "release"))) diff --git a/web_server.py b/web_server.py index 32173ebe..4cfa084a 100644 --- a/web_server.py +++ b/web_server.py @@ -29638,11 +29638,15 @@ def _fetch_liked_albums(profile_id: int): if discogs_cl.is_authenticated(): logger.info("[Your Albums] Fetching collection from Discogs...") releases = discogs_cl.get_user_collection() + from core.discogs_client import _tag_discogs_album_id for r in releases: database.upsert_liked_album( album_name=r['album_name'], artist_name=r['artist_name'], source_service='discogs', - source_id=str(r['release_id']), source_id_type='discogs', + # Collection items are always releases — store the ID tagged + # ('r') to match search/discography (#848), so every stored + # Discogs album ID is uniform and re-fetches route correctly. + source_id=_tag_discogs_album_id(r['release_id'], 'release'), source_id_type='discogs', image_url=r.get('image_url'), release_date=r.get('release_date', ''), total_tracks=r.get('total_tracks', 0), profile_id=profile_id )