mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 14:25:08 +00:00
fix: one retry layer for background fetches; CI installs the web requirements; one Discord invite (#657)
- BackgroundDataService: the session adapter retried connection errors 3x inside each attempt of the service's own retry loop (up to 16 connection attempts per request on a dead network). The adapter no longer retries; ESPN date chunks, which bypass the loop and skip a failed chunk, get a small connection retry of their own (_ConnectionRetryingSession). - CI installs web_interface/requirements.txt. The brotli header test now checks its intent (core never hand-sets br; requests may advertise it when a decoder is installed) instead of failing whenever brotli is present. - Every Discord link uses the LEDMatrix server's invite (RdrC37rEag). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -389,3 +389,43 @@ class TestPriorityIsAcceptedAndIgnored:
|
||||
rid = service.submit_fetch_request(
|
||||
"nfl", 2026, "http://example.invalid/x", cache_key="k", priority=5)
|
||||
assert service.get_result(rid).cached is True
|
||||
|
||||
|
||||
class TestOneRetryLayer:
|
||||
"""Each fetch used to retry at two levels: the session adapter retried a
|
||||
connection error three times inside every attempt of the service's own
|
||||
retry loop, so a dead network cost up to 16 connection attempts per
|
||||
request. Only the loop retries now; date chunks, which bypass it, get a
|
||||
small connection retry of their own."""
|
||||
|
||||
def test_the_session_adapters_do_not_retry(self, service):
|
||||
for prefix in ("http://", "https://"):
|
||||
assert service.session.get_adapter(prefix).max_retries.total == 0
|
||||
|
||||
def test_a_chunk_request_retries_a_connection_error(self, monkeypatch):
|
||||
import requests
|
||||
from src.background_data_service import _ConnectionRetryingSession
|
||||
monkeypatch.setattr(bds_module.time, "sleep", lambda s: None)
|
||||
inner = MagicMock()
|
||||
inner.get.side_effect = [requests.ConnectionError("blip"), "ok"]
|
||||
assert _ConnectionRetryingSession(inner).get("http://x") == "ok"
|
||||
assert inner.get.call_count == 2
|
||||
|
||||
def test_a_chunk_request_gives_up_after_its_attempts(self, monkeypatch):
|
||||
import requests
|
||||
from src.background_data_service import _ConnectionRetryingSession
|
||||
monkeypatch.setattr(bds_module.time, "sleep", lambda s: None)
|
||||
inner = MagicMock()
|
||||
inner.get.side_effect = requests.ConnectionError("down")
|
||||
with pytest.raises(requests.ConnectionError):
|
||||
_ConnectionRetryingSession(inner).get("http://x")
|
||||
assert inner.get.call_count == _ConnectionRetryingSession.ATTEMPTS
|
||||
|
||||
def test_other_errors_are_not_retried(self, monkeypatch):
|
||||
import requests
|
||||
from src.background_data_service import _ConnectionRetryingSession
|
||||
inner = MagicMock()
|
||||
inner.get.side_effect = requests.Timeout("slow")
|
||||
with pytest.raises(requests.Timeout):
|
||||
_ConnectionRetryingSession(inner).get("http://x")
|
||||
assert inner.get.call_count == 1
|
||||
|
||||
@@ -34,7 +34,14 @@ class TestSharedHeaders:
|
||||
assert APIHelper().session.headers['User-Agent'] == USER_AGENT
|
||||
|
||||
def test_api_helper_does_not_hand_set_brotli(self):
|
||||
assert 'br' not in APIHelper().session.headers.get('Accept-Encoding', '')
|
||||
# Accept-Encoding is left to requests, which advertises br only when
|
||||
# a brotli decoder is installed (flask-compress pulls one in, so the
|
||||
# web requirements do). What must not happen is core adding it by
|
||||
# hand, advertising a body the client may not be able to read.
|
||||
import requests
|
||||
assert 'accept-encoding' not in _lower_keys(DEFAULT_HTTP_HEADERS)
|
||||
assert (APIHelper().session.headers.get('Accept-Encoding')
|
||||
== requests.utils.default_headers()['Accept-Encoding'])
|
||||
|
||||
def test_logo_helper_sends_the_same_user_agent(self):
|
||||
from src.common.logo_helper import LogoHelper
|
||||
|
||||
Reference in New Issue
Block a user