Fix infinite Spotify rate limit loop from unguarded auth probes and swallowed errors
This commit is contained in:
parent
636af1f2f8
commit
bc22bdca07
2 changed files with 20 additions and 14 deletions
|
|
@ -441,18 +441,20 @@ class SpotifyClient:
|
|||
error_str = str(e)
|
||||
# Rate limit means we ARE authenticated — just throttled
|
||||
if "rate" in error_str.lower() or "429" in error_str:
|
||||
logger.warning("Spotify rate limited during auth check — treating as authenticated")
|
||||
# Check if there's a Retry-After header indicating a long ban
|
||||
# ANY rate limit on the auth probe means Spotify is actively throttling us.
|
||||
# Always activate a global ban — even with a short or missing Retry-After.
|
||||
# Without this, the probe→429→probe cycle repeats every ~60s forever.
|
||||
retry_after = None
|
||||
if hasattr(e, 'headers') and e.headers:
|
||||
retry_after = e.headers.get('Retry-After') or e.headers.get('retry-after')
|
||||
if retry_after:
|
||||
try:
|
||||
delay = int(retry_after)
|
||||
if delay > _LONG_RATE_LIMIT_THRESHOLD:
|
||||
_set_global_rate_limit(delay, 'is_spotify_authenticated')
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
try:
|
||||
delay = int(retry_after) if retry_after else 0
|
||||
except (ValueError, TypeError):
|
||||
delay = 0
|
||||
# Minimum 10 minutes for auth probe 429s — these indicate persistent throttling
|
||||
ban_duration = max(delay, 600)
|
||||
_set_global_rate_limit(ban_duration, 'is_spotify_authenticated')
|
||||
logger.warning(f"Auth probe rate limited — activating {ban_duration}s global ban")
|
||||
result = True
|
||||
else:
|
||||
logger.debug(f"Spotify authentication check failed: {e}")
|
||||
|
|
|
|||
|
|
@ -149,12 +149,14 @@ class SpotifyWorker:
|
|||
time.sleep(min(cooldown, 60))
|
||||
continue
|
||||
|
||||
# Auth guard — don't process anything without Spotify auth
|
||||
if not self.client.is_spotify_authenticated():
|
||||
# Try reloading config in case user re-authenticated via settings
|
||||
# Auth guard — check if Spotify client is configured (no API call).
|
||||
# We intentionally avoid calling is_spotify_authenticated() here
|
||||
# because it makes an API probe that can re-trigger rate limits
|
||||
# and lock users in an infinite rate-limit loop.
|
||||
if not self.client.sp:
|
||||
self.client.reload_config()
|
||||
if not self.client.is_spotify_authenticated():
|
||||
logger.debug("Spotify not authenticated, sleeping 30s...")
|
||||
if not self.client.sp:
|
||||
logger.debug("Spotify not configured, sleeping 30s...")
|
||||
time.sleep(30)
|
||||
continue
|
||||
|
||||
|
|
@ -343,6 +345,8 @@ class SpotifyWorker:
|
|||
elif item_type == 'track_individual':
|
||||
self._process_track_individual(item)
|
||||
|
||||
except SpotifyRateLimitError:
|
||||
raise # Propagate to main loop so it activates the sleep/ban guard
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing {item.get('type')} '{item.get('name', '')}': {e}")
|
||||
self.stats['errors'] += 1
|
||||
|
|
|
|||
Loading…
Reference in a new issue