mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 06:15:09 +00:00
fix: web UI and src.common bugs (wifi wrong-password, plugin icon, starlark toggle, API caching, scroll/logo/font helpers) (#646)
- wifi: keep the "wrong_password:" prefix through the restore/AP fallback so the UI's incorrect-password prompt fires again. - /plugins/installed returns the manifest's icon (string only). - /starlark/apps/<id>/toggle coerces `enabled` and delegates to _toggle_starlark_app (disk before memory, no KeyError, "false" is false). - /api/v3/ JSON GETs are sent Cache-Control: no-store; non-JSON keeps 5s. - ScrollHelper.set_scrolling_image converts non-RGB input (alpha onto black); create/set_scrolling_image reset last_update_time like reset_scroll. - LogoHelper backs off a failed download per path for MISSING_LOGO_RECHECK_SECONDS; cleared on invalidate/clear_cache. - refresh_placeholder_timestamp saves atomically. - FontManager.clear_cache / _clear_plugin_font_cache bump cache_generation. - Odds manager: per-game logs to DEBUG; JSON decode error caught before RequestException (same cooldown). - element_style mangled continuations; startup validator skips null plugin blocks and reuses the controller's discovery. - src/common/README lists frame_timing, json_body, render_gate. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -123,8 +123,10 @@ class BaseOddsManager:
|
||||
# Check cache first
|
||||
cached_data = self.cache_manager.get_with_auto_strategy(cache_key)
|
||||
|
||||
# Per-game chatter, logged on every update of every game on the
|
||||
# slate: debug, not the journal.
|
||||
if cached_data:
|
||||
self.logger.info(f"Using cached odds from ESPN for {cache_key}")
|
||||
self.logger.debug(f"Using cached odds from ESPN for {cache_key}")
|
||||
return cached_data
|
||||
|
||||
if time.monotonic() < self._skip_network_until:
|
||||
@@ -137,7 +139,7 @@ class BaseOddsManager:
|
||||
self._skip_network_until - time.monotonic())
|
||||
return None
|
||||
|
||||
self.logger.info(f"Cache miss - fetching fresh odds from ESPN for {cache_key}")
|
||||
self.logger.debug(f"Cache miss - fetching fresh odds from ESPN for {cache_key}")
|
||||
|
||||
try:
|
||||
# Map league names to ESPN API format
|
||||
@@ -151,7 +153,7 @@ class BaseOddsManager:
|
||||
|
||||
espn_league = league_mapping.get(league, league)
|
||||
url = f"{self.base_url}/{sport}/leagues/{espn_league}/events/{event_id}/competitions/{event_id}/odds"
|
||||
self.logger.info(f"Requesting odds from URL: {url}")
|
||||
self.logger.debug(f"Requesting odds from URL: {url}")
|
||||
|
||||
response = self.session.get(url, timeout=self.request_timeout)
|
||||
response.raise_for_status()
|
||||
@@ -163,9 +165,9 @@ class BaseOddsManager:
|
||||
|
||||
odds_data = self._extract_espn_data(raw_data)
|
||||
if odds_data:
|
||||
self.logger.info(f"Successfully extracted odds data: {odds_data}")
|
||||
self.logger.debug(f"Successfully extracted odds data: {odds_data}")
|
||||
self.cache_manager.set(cache_key, odds_data, ttl=interval)
|
||||
self.logger.info(f"Saved odds data to cache for {cache_key} with TTL {interval}s")
|
||||
self.logger.debug(f"Saved odds data to cache for {cache_key} with TTL {interval}s")
|
||||
else:
|
||||
self.logger.debug(f"No odds data available for {cache_key}")
|
||||
# Cache the absence too, so the game is not re-requested
|
||||
@@ -174,14 +176,19 @@ class BaseOddsManager:
|
||||
|
||||
return odds_data
|
||||
|
||||
# Before RequestException: requests' JSONDecodeError subclasses it, so
|
||||
# listed second this branch never ran and a bad body was reported as a
|
||||
# failed fetch. It holds off like a failed fetch did, so only the
|
||||
# message changes.
|
||||
except (json.JSONDecodeError, requests.exceptions.JSONDecodeError):
|
||||
self._skip_network_until = time.monotonic() + self._FAILURE_COOLDOWN
|
||||
self.logger.error(f"Error decoding JSON response from ESPN API for {cache_key}.")
|
||||
except requests.exceptions.RequestException as e:
|
||||
self._skip_network_until = time.monotonic() + self._FAILURE_COOLDOWN
|
||||
self.logger.error(
|
||||
"Error fetching odds from ESPN API for %s: %s. Holding off on odds "
|
||||
"for %.0fs so a slate of games does not pay this timeout each.",
|
||||
cache_key, e, self._FAILURE_COOLDOWN)
|
||||
except json.JSONDecodeError:
|
||||
self.logger.error(f"Error decoding JSON response from ESPN API for {cache_key}.")
|
||||
|
||||
return self.cache_manager.get_with_auto_strategy(cache_key)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user