Share metadata source priority

Centralize the ordered metadata source list and source-priority helper so album completeness and the repair worker follow the same Deezer/iTunes-first fallback order. This also removes the last duplicate priority logic from the touched repair paths.
This commit is contained in:
Antti Kettunen 2026-04-15 07:48:19 +03:00
parent 8a1ae00946
commit 106d202ccc
3 changed files with 26 additions and 31 deletions

View file

@ -17,6 +17,9 @@ logger = get_logger("metadata_service")
MetadataProvider = Literal["spotify", "itunes", "auto"] MetadataProvider = Literal["spotify", "itunes", "auto"]
# Ordered by fallback preference. Higher-priority sources appear earlier.
METADATA_SOURCE_PRIORITY = ('deezer', 'itunes', 'spotify', 'discogs', 'hydrabase')
_client_cache_lock = threading.RLock() _client_cache_lock = threading.RLock()
_client_cache: Dict[str, Any] = {} _client_cache: Dict[str, Any] = {}
@ -65,6 +68,20 @@ def get_primary_client():
return get_client_for_source(get_primary_source()) return get_client_for_source(get_primary_source())
def get_source_priority(preferred_source: str):
"""Return supported sources with the preferred source first."""
ordered = []
if preferred_source in METADATA_SOURCE_PRIORITY:
ordered.append(preferred_source)
for source in METADATA_SOURCE_PRIORITY:
if source not in ordered:
ordered.append(source)
return ordered
def get_client_for_source(source: str): def get_client_for_source(source: str):
"""Get the client object for an exact metadata source. """Get the client object for an exact metadata source.

View file

@ -3,6 +3,7 @@
from core.metadata_service import ( from core.metadata_service import (
get_album_tracks_for_source, get_album_tracks_for_source,
get_primary_source, get_primary_source,
get_source_priority,
) )
from core.repair_jobs import register_job from core.repair_jobs import register_job
from core.repair_jobs.base import JobContext, JobResult, RepairJob from core.repair_jobs.base import JobContext, JobResult, RepairJob
@ -252,7 +253,7 @@ class AlbumCompletenessJob(RepairJob):
def _get_expected_total(self, context, primary_source, album_ids): def _get_expected_total(self, context, primary_source, album_ids):
"""Try to get the expected track count from the active metadata provider first.""" """Try to get the expected track count from the active metadata provider first."""
for source in self._iter_source_priority(primary_source): for source in get_source_priority(primary_source):
album_id = self._get_album_id_for_source(source, album_ids) album_id = self._get_album_id_for_source(source, album_ids)
if not album_id: if not album_id:
continue continue
@ -284,7 +285,7 @@ class AlbumCompletenessJob(RepairJob):
conn.close() conn.close()
api_tracks = None api_tracks = None
for source in self._iter_source_priority(primary_source): for source in get_source_priority(primary_source):
source_album_id = self._get_album_id_for_source(source, album_ids) source_album_id = self._get_album_id_for_source(source, album_ids)
if not source_album_id: if not source_album_id:
continue continue
@ -336,29 +337,12 @@ class AlbumCompletenessJob(RepairJob):
except Exception: except Exception:
return 'deezer' return 'deezer'
def _iter_source_priority(self, primary_source: str):
"""Yield supported sources in priority order."""
supported = ('spotify', 'itunes', 'deezer', 'discogs', 'hydrabase')
ordered = []
if primary_source in supported:
ordered.append(primary_source)
for source in supported:
if source not in ordered:
ordered.append(source)
return ordered
def _get_album_id_for_source(self, source: str, album_ids: dict) -> str: def _get_album_id_for_source(self, source: str, album_ids: dict) -> str:
return album_ids.get(source, '') return album_ids.get(source, '')
def _get_album_tracks(self, source: str, album_id: str): def _get_album_tracks(self, source: str, album_id: str):
"""Fetch album tracks from a specific source.""" """Fetch album tracks from a specific source."""
try: try:
if source not in ('spotify', 'itunes', 'deezer', 'discogs', 'hydrabase'):
return None
return get_album_tracks_for_source(source, album_id) return get_album_tracks_for_source(source, album_id)
except Exception as e: except Exception as e:
logger.debug("Error getting %s album tracks for %s: %s", source.capitalize(), album_id, e) logger.debug("Error getting %s album tracks for %s: %s", source.capitalize(), album_id, e)

View file

@ -18,7 +18,11 @@ from difflib import SequenceMatcher
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
from core.metadata_service import get_album_tracks_for_source, get_primary_source from core.metadata_service import (
get_album_tracks_for_source,
get_source_priority,
get_primary_source,
)
from core.repair_jobs import get_all_jobs from core.repair_jobs import get_all_jobs
from core.repair_jobs.base import JobContext, JobResult, RepairJob from core.repair_jobs.base import JobContext, JobResult, RepairJob
from utils.logging_config import get_logger from utils.logging_config import get_logger
@ -1930,17 +1934,7 @@ class RepairWorker:
'hydrabase': hydrabase_album_id, 'hydrabase': hydrabase_album_id,
} }
def _source_priority(source_name: str): for source in get_source_priority(primary_source):
supported = ('spotify', 'itunes', 'deezer', 'discogs', 'hydrabase')
ordered = []
if source_name in supported:
ordered.append(source_name)
for source in supported:
if source not in ordered:
ordered.append(source)
return ordered
for source in _source_priority(primary_source):
fid = album_sources.get(source, '') fid = album_sources.get(source, '')
if not fid: if not fid:
continue continue