fix: stop the Tidal token-refresh loop (regression from #949)
#949 moved the "token still valid -> return True" short-circuit in TidalClient.is_authenticated() into the boot-phase branch ONLY, so after boot every call fell through to the silent refresh regardless of whether the token was actually expired. With multiple workers polling Tidal every few seconds, that produced a constant "access token expired -> refresh -> success" loop (wolf39us logs) — needless token churn, not an actual auth problem. Restored the valid-token short-circuit on the post-boot path. The download client is unaffected (it defers the tidalapi session differently, no manual expiry loop). 3 regression tests: valid token post-boot does NOT refresh, expired token still does, valid token during boot returns True without probing.
This commit is contained in:
parent
68d52a1b3f
commit
4b8ddad9ff
2 changed files with 52 additions and 0 deletions
|
|
@ -529,6 +529,12 @@ class TidalClient:
|
|||
return True
|
||||
return bool(self.access_token and self.refresh_token)
|
||||
|
||||
# Token still valid — no refresh needed. (Restored: #949 moved this short-circuit
|
||||
# into the boot-phase branch only, so every post-boot call fell through to the
|
||||
# refresh below — a constant silent-refresh loop on a perfectly valid token.)
|
||||
if self.access_token and time.time() < self.token_expires_at:
|
||||
return True
|
||||
|
||||
# Backoff: if refresh recently failed, don't retry for 5 minutes
|
||||
if hasattr(self, '_refresh_failed_at') and self._refresh_failed_at:
|
||||
if time.time() - self._refresh_failed_at < 300:
|
||||
|
|
|
|||
46
tests/test_tidal_token_refresh_loop.py
Normal file
46
tests/test_tidal_token_refresh_loop.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
"""Regression: post-boot, is_authenticated() must NOT refresh a still-valid Tidal token.
|
||||
|
||||
#949 moved the "token still valid -> return True" short-circuit into the boot-phase branch
|
||||
only, so every post-boot call fell through to the silent refresh — a constant-refresh loop
|
||||
(wolf's logs: "access token expired -> refresh -> success" every few seconds)."""
|
||||
|
||||
import time
|
||||
|
||||
import core.boot_phase as boot_phase
|
||||
from core.tidal_client import TidalClient
|
||||
|
||||
|
||||
def _client(expires_at):
|
||||
c = TidalClient.__new__(TidalClient)
|
||||
c.access_token = "tok"
|
||||
c.refresh_token = "refresh"
|
||||
c.token_expires_at = expires_at
|
||||
c._refresh_calls = 0
|
||||
|
||||
def _fake_refresh():
|
||||
c._refresh_calls += 1
|
||||
return True
|
||||
|
||||
c._refresh_access_token = _fake_refresh
|
||||
return c
|
||||
|
||||
|
||||
def test_valid_token_does_not_refresh_post_boot(monkeypatch):
|
||||
monkeypatch.setattr(boot_phase, "_boot_active", False) # post-boot
|
||||
c = _client(time.time() + 3600) # valid for an hour
|
||||
assert c.is_authenticated() is True
|
||||
assert c._refresh_calls == 0 # MUST NOT refresh a valid token
|
||||
|
||||
|
||||
def test_expired_token_still_refreshes_post_boot(monkeypatch):
|
||||
monkeypatch.setattr(boot_phase, "_boot_active", False)
|
||||
c = _client(time.time() - 10) # expired
|
||||
assert c.is_authenticated() is True
|
||||
assert c._refresh_calls == 1 # expired -> one refresh
|
||||
|
||||
|
||||
def test_valid_token_returns_true_during_boot(monkeypatch):
|
||||
monkeypatch.setattr(boot_phase, "_boot_active", True) # boot phase
|
||||
c = _client(time.time() + 3600)
|
||||
assert c.is_authenticated() is True
|
||||
assert c._refresh_calls == 0 # boot never probes/refreshes
|
||||
Loading…
Reference in a new issue