Don't apply the real-API daily budget / cooldown while bridging via Spotify Free
#798 follow-up. The Spotify enrichment worker's daily budget and post-ban cooldown both exist to protect the REAL authenticated API from bans. But the worker bridges to the no-creds Spotify Free source during a ban (a different, anonymous path), and those guards weren't free-aware: - the budget guard slept the worker when the daily cap was hit, blocking free work for no reason, - free-served items still incremented the budget counter, draining the real-API cap with calls that never touched the real API (so you'd return from a ban with budget already spent), and - the post-ban cooldown slept the worker even when serving via free. Fix: compute free_serving = client._free_active() once per loop (defensively wrapped → False on error → original behavior). When free_serving: - skip the daily-budget guard, - skip the post-ban-cooldown guard, - don't increment the daily budget. So the budget is now strictly a cap on REAL Spotify API usage; free runs unthrottled by it (the free client keeps its own inter-call pacing). The decision input (_free_active) is already pinned by the gate-model tests (free True exactly when rate-limited+Free / Free-primary, False when authed+healthy). Full suite clean (only pre-existing soundcloud /app env failures remain).
This commit is contained in:
parent
3fcfa900bd
commit
6b5506dee4
1 changed files with 20 additions and 5 deletions
|
|
@ -209,8 +209,19 @@ class SpotifyWorker:
|
||||||
interruptible_sleep(self._stop_event, min(remaining, 60)) # Check again every 60s max
|
interruptible_sleep(self._stop_event, min(remaining, 60)) # Check again every 60s max
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Daily budget guard — worker-only cap to avoid saturating Spotify rate limits
|
# Is the worker serving via the no-creds Spotify Free source this
|
||||||
if self._is_daily_budget_exhausted():
|
# iteration? The daily budget and post-ban cooldown both exist to
|
||||||
|
# protect the REAL authenticated API from bans — they don't apply
|
||||||
|
# to free (a different, anonymous path). Computed once and reused
|
||||||
|
# below; the loop already probes auth, so no extra quota cost.
|
||||||
|
try:
|
||||||
|
free_serving = self.client._free_active()
|
||||||
|
except Exception:
|
||||||
|
free_serving = False
|
||||||
|
|
||||||
|
# Daily budget guard — worker-only cap to avoid saturating the REAL
|
||||||
|
# Spotify API. Skipped while serving via free (free isn't that API).
|
||||||
|
if not free_serving and self._is_daily_budget_exhausted():
|
||||||
budget = self._get_daily_budget_info()
|
budget = self._get_daily_budget_info()
|
||||||
resets_in = budget['resets_in_seconds']
|
resets_in = budget['resets_in_seconds']
|
||||||
logger.info(f"Daily enrichment budget exhausted ({budget['used']}/{budget['limit']}), "
|
logger.info(f"Daily enrichment budget exhausted ({budget['used']}/{budget['limit']}), "
|
||||||
|
|
@ -219,8 +230,9 @@ class SpotifyWorker:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Post-ban cooldown guard — after ban expires, wait before resuming
|
# Post-ban cooldown guard — after ban expires, wait before resuming
|
||||||
# to avoid immediately re-triggering the rate limit
|
# to avoid immediately re-triggering the rate limit. Only matters
|
||||||
cooldown = self.client.get_post_ban_cooldown_remaining()
|
# for the real API, so skip it while serving via free.
|
||||||
|
cooldown = 0 if free_serving else self.client.get_post_ban_cooldown_remaining()
|
||||||
if cooldown > 0:
|
if cooldown > 0:
|
||||||
logger.debug(f"Post-ban cooldown active ({cooldown}s left), sleeping...")
|
logger.debug(f"Post-ban cooldown active ({cooldown}s left), sleeping...")
|
||||||
interruptible_sleep(self._stop_event, min(cooldown, 60))
|
interruptible_sleep(self._stop_event, min(cooldown, 60))
|
||||||
|
|
@ -261,7 +273,10 @@ class SpotifyWorker:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._process_item(item)
|
self._process_item(item)
|
||||||
self._increment_daily_budget()
|
# Only real-API work counts toward the daily cap — free-served
|
||||||
|
# items don't touch the authenticated API's quota.
|
||||||
|
if not free_serving:
|
||||||
|
self._increment_daily_budget()
|
||||||
interruptible_sleep(self._stop_event, self.inter_item_sleep)
|
interruptible_sleep(self._stop_event, self.inter_item_sleep)
|
||||||
|
|
||||||
except SpotifyRateLimitError:
|
except SpotifyRateLimitError:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue