various/stale

This commit is contained in:
2026-01-25 13:14:00 -05:00
parent 10ccf8c8eb
commit 97fd7dd67d
14 changed files with 501 additions and 64 deletions

View File

@@ -1081,6 +1081,27 @@ class SRUtil:
return combined_metadata
except Exception as e:
err_str = str(e).lower()
# If this is a permanent not found error, abort retries immediately
if any(
phrase in err_str
for phrase in [
"track not found",
"not found",
"404",
"does not exist",
"no longer available",
"asset is not ready",
]
):
logging.error(
"Metadata fetch permanent failure for track %s: %s (not retrying)",
track_id,
str(e),
)
raise MetadataFetchError(
f"Metadata fetch failed permanently for track {track_id}: {e}"
)
# Exponential backoff with jitter for 429 or other errors
delay = self.RETRY_DELAY * (2 ** (attempt - 1)) + random.uniform(0, 0.5)
if attempt < self.MAX_METADATA_RETRIES:
@@ -1179,6 +1200,47 @@ class SRUtil:
if not tracks:
return None
# Prefer exact title matches first (highest confidence)
exact_title_matches = []
for t in tracks:
found_title = t.get("title")
if found_title and found_title.strip().lower() == song.strip().lower():
exact_title_matches.append(t)
if exact_title_matches:
logging.info(f"SR: {len(exact_title_matches)} exact title matches found")
tracks = exact_title_matches
else:
# Prefer tracks that match artist/title fuzzily
filtered_by_metadata = []
for t in tracks:
found_artist = (
t.get("artist", {}).get("name")
if isinstance(t.get("artist"), dict)
else t.get("artist")
)
found_album = (
t.get("album", {}).get("title") if t.get("album") else None
)
found_title = t.get("title")
try:
if self.is_metadata_match(
artist, album, song, found_artist, found_album, found_title
):
filtered_by_metadata.append(t)
except Exception:
# On any error, skip strict metadata matching for this candidate
continue
if filtered_by_metadata:
logging.info(
f"SR: {len(filtered_by_metadata)} candidates after metadata filtering"
)
tracks = filtered_by_metadata
else:
logging.info(
"SR: No candidates passed metadata match filter; falling back to search results"
)
# If duration provided, select the track with closest duration match
if duration is not None:
tracks_with_diff = [
@@ -1195,7 +1257,88 @@ class SRUtil:
best_track = tracks[0]
track_id = best_track.get("id")
logging.info(f"SR: Using track ID {track_id}")
# Ensure the selected candidate reasonably matches expected metadata
selected_artist = (
best_track.get("artist", {}).get("name")
if isinstance(best_track.get("artist"), dict)
else best_track.get("artist")
)
selected_title = best_track.get("title")
if not self.is_metadata_match(
artist,
album,
song,
selected_artist,
best_track.get("album", {}).get("title")
if best_track.get("album")
else None,
selected_title,
):
# Try to find another candidate that does match metadata
logging.warning(
"SR: Selected candidate failed metadata check: id=%s artist=%s title=%s; searching for better match",
track_id,
selected_artist,
selected_title,
)
found_better = None
for candidate in tracks:
cand_artist = (
candidate.get("artist", {}).get("name")
if isinstance(candidate.get("artist"), dict)
else candidate.get("artist")
)
cand_title = candidate.get("title")
if self.is_metadata_match(
artist,
album,
song,
cand_artist,
candidate.get("album", {}).get("title")
if candidate.get("album")
else None,
cand_title,
):
found_better = candidate
break
if found_better:
logging.warning(
"SR: Switching to better candidate id=%s artist=%s title=%s",
found_better.get("id"),
(
found_better.get("artist", {}).get("name")
if isinstance(found_better.get("artist"), dict)
else found_better.get("artist")
),
found_better.get("title"),
)
best_track = found_better
track_id = best_track.get("id")
else:
# No matching candidate passed metadata checks; log candidates and abort
logging.warning(
"SR: No candidates passed metadata checks for %s - %s; candidates: %s",
artist,
song,
[
{
"id": t.get("id"),
"artist": (
t.get("artist", {}).get("name")
if isinstance(t.get("artist"), dict)
else t.get("artist")
),
"title": t.get("title"),
"duration": t.get("duration"),
}
for t in tracks[:10]
],
)
return None
logging.info(
f"SR: Using track ID {track_id} (artist={best_track.get('artist')}, title={best_track.get('title')})"
)
if not track_id:
return None