diff --git a/core/spotify_client.py b/core/spotify_client.py index eb530c1d..815409aa 100644 --- a/core/spotify_client.py +++ b/core/spotify_client.py @@ -134,6 +134,31 @@ def _clear_rate_limit(): logger.info("Global rate limit ban cleared (including post-ban cooldown)") +def _detect_and_set_rate_limit(exception, endpoint_name="unknown"): + """Check if a Spotify exception is a 429 rate limit and activate global ban if so. + Returns True if rate limit was detected.""" + error_str = str(exception) + if "429" in error_str or "rate limit" in error_str.lower(): + # Try to extract Retry-After + retry_after = None + if hasattr(exception, 'headers') and exception.headers: + retry_after = exception.headers.get('Retry-After') or exception.headers.get('retry-after') + if retry_after: + try: + delay = int(retry_after) + except (ValueError, TypeError): + delay = 300 # Default 5 min if can't parse + else: + # Spotipy "Max Retries" means it already exhausted retries — assume long ban + if "max retries" in error_str.lower(): + delay = 600 # 10 min default for exhausted retries + else: + delay = 300 + _set_global_rate_limit(delay, endpoint_name) + return True + return False + + def rate_limited(func): """Decorator to enforce rate limiting on Spotify API calls with retry and exponential backoff""" @wraps(func) @@ -896,6 +921,7 @@ class SpotifyClient: return album_data except Exception as e: + _detect_and_set_rate_limit(e, 'get_album') logger.error(f"Error fetching album via Spotify: {e}") # Fall through to iTunes fallback @@ -1007,6 +1033,7 @@ class SpotifyClient: try: return self.sp.artist(artist_id) except Exception as e: + _detect_and_set_rate_limit(e, 'get_artist') logger.error(f"Error fetching artist via Spotify: {e}") # Fall through to iTunes fallback diff --git a/web_server.py b/web_server.py index 6ec4de0b..49c9d235 100644 --- a/web_server.py +++ b/web_server.py @@ -29235,6 +29235,8 @@ def enrich_similar_artists(): image_url=img_url, genres=genres, popularity=pop ) except Exception as e: + from core.spotify_client import _detect_and_set_rate_limit + _detect_and_set_rate_limit(e, 'enrich_similar_artists') print(f"Error enriching Spotify batch: {e}") else: from core.itunes_client import iTunesClient