Skip to content

fix(sports): stop has_live_content() flooding the log during live games - #241

Merged
ChuckBuilds merged 2 commits into
mainfrom
fix/live-content-log-throttle
Aug 3, 2026
Merged

fix(sports): stop has_live_content() flooding the log during live games#241
ChuckBuilds merged 2 commits into
mainfrom
fix/live-content-log-throttle

Conversation

@ChuckBuilds

@ChuckBuilds ChuckBuilds commented Aug 2, 2026

Copy link
Copy Markdown
Owner

The bug

has_live_content() is called from the display path — once per frame in Vegas mode, not once per update. Both plugins emitted a per-league INFO line whenever that league had any live game, and those lines had no throttle at all.

The one throttle that existed guarded only the final summary, and it skipped even that whenever the answer was True:

# Always log True immediately (important), but only log False every 60 seconds
should_log = result or (current_time - self._last_live_content_false_log >= self._live_content_log_interval)

"Always log True immediately" is harmless for an occasional caller and ruinous for a per-frame one.

Measured on hardware

A 512x64 device with nine live MLB games:

before after
has_live_content lines/min 13,871 3
total journal lines/min 14,151 253
share of the journal 98% ~1%

It buried every other message and put needless journald writes on the render path. The tell-tale line, note the answer is False the entire time — the per-league lines fire regardless of what the function returns:

has_live_content: MLB live_games=9, filtered_live_games=9, mlb_live=False

Football was quiet only because it is the off-season. The same code would have started spamming at kickoff, which is why it is fixed here rather than after the fact.

The fix

Both plugins now:

  • fold the per-league lines into the single summary, which carries the same counts — has_live_content() returning False: mlb_live=False, milb_live=False, ncaa_live=False (live games: MLB=7), strictly more informative than before in a quarter of the lines;
  • log that summary when the answer changes — a game starting or ending, a league flipping — then at most once per interval while it holds, so a steady state stays visible in the log.

baseball-scoreboard 1.20.3 → 1.20.4, football-scoreboard 2.9.3 → 2.9.4.

Verification

  • New regression suites in both plugins (test_live_content_log_throttle.py): 200 identical live calls → 1 line; a count or boolean change → immediate line; unchanged → re-logs after the interval; False still throttled. 4/4 pass each.
  • Safety harness: baseball 24/24 PASS, football 16/16 PASS, no golden drift.
  • Module collisions: clean across 42 plugins.
  • Existing suites: pre-existing failures only — each one confirmed failing identically on origin/main (missing config template, missing font, a config-reload assertion, a test-mode exception, adaptive-layout and dynamic-duration).
  • Soaked on real hardware (devpi, 512x64): both plugins load clean, panel still rendering, rates above are from that device.

Note for the sports unification

The same copy-pasted throttle block is in hockey-scoreboard (manager.py:2117) and basketball-scoreboard (manager.py:1440). Those are milder — only the summary bypasses the throttle on True, so it is one line per frame while a game is live rather than three — and they are not touched here. Given phase B5 is about to consolidate these plugins onto src/base_classes/sports/, that logging probably wants to land in core once rather than be patched in four copies.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Udr6MfaFLUPhX5Fgo67Jf5

Summary by CodeRabbit

  • Improvements

    • Reduced live-game logging for baseball and football scoreboards.
    • Consolidated per-league messages into a single summary.
    • Logs update immediately when live-game status changes and limit unchanged updates to once per minute.
  • Releases

    • Updated Baseball Scoreboard to version 1.21.1.
    • Updated Football Scoreboard to version 2.10.1.

has_live_content() is called from the display path -- once per *frame* in
Vegas mode, not once per update. Both plugins emitted a per-league INFO line
whenever that league had any live game, and those lines had no throttle at
all. The one throttle that existed guarded only the final summary, and it
skipped even that whenever the answer was True ("always log True immediately"),
which is harmless for an occasional caller and ruinous for a per-frame one.

Measured on a 512x64 device with nine live MLB games: 13,871 lines a minute,
98% of the entire journal. That buried every other message and put needless
journald writes on the render path. Football was quiet only because it is the
off-season; the same code would have started spamming at kickoff.

Both plugins now fold the per-league lines into the single summary, which
carries the same counts (`live games: MLB=7`), and log it when the answer
*changes* -- a game starting or ending, a league flipping -- then at most once
per interval while it holds, so a steady state is still visible.

Same device after the fix: 3 lines a minute.

baseball-scoreboard 1.20.3 -> 1.20.4, football-scoreboard 2.9.3 -> 2.9.4.

Verified: new regression suites in both plugins (200 identical live calls ->
1 line; change -> immediate line; unchanged -> re-logs after the interval;
False still throttled), safety harness 24/24 and 16/16 PASS with no golden
drift, module-collision check clean, and both fixes soaked on devpi.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Udr6MfaFLUPhX5Fgo67Jf5
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Both scoreboard plugins now consolidate live-content logging into throttled summaries. Regression tests cover state changes, repeated results, and interval-based re-logging. Plugin versions, manifests, catalog entries, and changelogs were updated.

Changes

Scoreboard live-content logging

Layer / File(s) Summary
Baseball live-content logging and tests
plugins/baseball-scoreboard/manager.py, plugins/baseball-scoreboard/test_live_content_log_throttle.py, plugins/baseball-scoreboard/CHANGELOG.md
The manager records per-league counts and logs one sorted summary when state changes or after 60 seconds. Tests cover repeated results, count changes, boolean changes, and interval re-logging.
Football live-content logging and tests
plugins/football-scoreboard/manager.py, plugins/football-scoreboard/test_live_content_log_throttle.py, plugins/football-scoreboard/CHANGELOG.md
The manager uses the same consolidated throttling behavior for NFL and NCAA Football results. Tests cover repeated results, count changes, boolean changes, and interval re-logging.
Plugin release metadata
plugins.json, plugins/baseball-scoreboard/manifest.json, plugins/football-scoreboard/manifest.json
Catalog and manifest versions advance to 1.21.1 and 2.10.1. Both manifests add release entries dated 2026-08-03 with minimum LEDMatrix version 2.0.0.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: preventing has_live_content() from flooding logs during live games.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/live-content-log-throttle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 32 complexity

Metric Results
Complexity 32

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

…s passed

#235 landed while this PR was open and bumped both plugins past it --
baseball to 1.21.0 and football to 2.10.0 -- which stranded this branch's
1.20.4 / 2.9.4 below main. CI rejects a bump that is not above main's version,
and users already on the higher version would never receive the change, so the
fix is re-released on top rather than merged as-is:

  baseball-scoreboard  1.20.4 -> 1.21.1
  football-scoreboard   2.9.4 -> 2.10.1

Conflicts and how each was resolved:

- Both manifests: git collapsed the two competing head insertions into one
  entry, which silently drops the entry main shipped. Kept BOTH -- this
  branch's, renumbered and on top, then #235's 1.21.0 / 2.10.0 beneath it.
- Both CHANGELOGs: same shape, same resolution. Neither release note is lost.
- plugins.json: regenerated from main rather than merged textually
  (`git show origin/main:plugins.json > plugins.json && python3
  update_registry.py`). The diff against main is exactly the two version
  bumps plus the regenerated timestamp.
- Both manager.py files auto-merged: #235 added a favorite-check module and
  called it from a different region than the has_live_content() logging this
  branch rewrote.

Verified on the merged tree:
- the throttle changes are intact and the old unthrottled per-league
  logger.info lines are gone from both plugins
- #235's favorite_check modules are present and still wired into both
  managers
- safety harness 24/24 (baseball) and 16/16 (football), no golden drift
- module-collision check clean across 42 plugins
- manifest version, versions[0] and plugins.json latest_version agree
- plugin test suites: same 4 baseball / 3 football failures as origin/main,
  each confirmed pre-existing against a worktree of the new main

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Udr6MfaFLUPhX5Fgo67Jf5

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
plugins/football-scoreboard/manager.py (1)

1978-1996: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Include active celebrations in the throttled state log.

has_live_content() returns True for an active celebration before this block, at Lines 1801-1804. That path does not update _last_live_content_state or _last_live_content_log. A celebration that starts while no game is live is not logged as a state change. Route the celebration result through the same state-tracking path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/football-scoreboard/manager.py` around lines 1978 - 1996, Update
has_live_content() so the active-celebration early-return path participates in
the same _last_live_content_state and _last_live_content_log throttling used by
the shown logging block. Route the celebration result through the shared
state/logging flow, preserving the existing result and live-game count details
while ensuring a celebration starting without a live game is logged as a state
change.
plugins/baseball-scoreboard/manager.py (1)

1098-1122: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Use the shared cache for FavoriteTeamCheck network I/O.

Both managers create FavoriteTeamCheck without self.cache_manager, and _fetch_teams() / _schedule_note() call ESPN APIs directly via requests. Cache these responses through the plugin’s shared cache using cache_manager in the same pattern as the scoreboard managers.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/baseball-scoreboard/manager.py` around lines 1098 - 1122, The
FavoriteTeamCheck instances created in _check_favorite_teams in
plugins/baseball-scoreboard/manager.py lines 1098-1122 and
plugins/football-scoreboard/manager.py lines 984-1008 must use the shared
cache_manager. Pass each manager’s cache_manager when constructing
FavoriteTeamCheck, and update its _fetch_teams and _schedule_note request paths
to cache ESPN responses through that shared cache following the existing
scoreboard-manager pattern.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@plugins/baseball-scoreboard/manager.py`:
- Around line 1098-1122: The FavoriteTeamCheck instances created in
_check_favorite_teams in plugins/baseball-scoreboard/manager.py lines 1098-1122
and plugins/football-scoreboard/manager.py lines 984-1008 must use the shared
cache_manager. Pass each manager’s cache_manager when constructing
FavoriteTeamCheck, and update its _fetch_teams and _schedule_note request paths
to cache ESPN responses through that shared cache following the existing
scoreboard-manager pattern.

In `@plugins/football-scoreboard/manager.py`:
- Around line 1978-1996: Update has_live_content() so the active-celebration
early-return path participates in the same _last_live_content_state and
_last_live_content_log throttling used by the shown logging block. Route the
celebration result through the shared state/logging flow, preserving the
existing result and live-game count details while ensuring a celebration
starting without a live game is logged as a state change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a0acc46-b1c6-4f88-b480-ec7d624df4e3

📥 Commits

Reviewing files that changed from the base of the PR and between 1a02a33 and a0a2b7a.

📒 Files selected for processing (7)
  • plugins.json
  • plugins/baseball-scoreboard/CHANGELOG.md
  • plugins/baseball-scoreboard/manager.py
  • plugins/baseball-scoreboard/manifest.json
  • plugins/football-scoreboard/CHANGELOG.md
  • plugins/football-scoreboard/manager.py
  • plugins/football-scoreboard/manifest.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/football-scoreboard/CHANGELOG.md

@ChuckBuilds
ChuckBuilds merged commit cca2514 into main Aug 3, 2026
4 checks passed
@ChuckBuilds
ChuckBuilds deleted the fix/live-content-log-throttle branch August 5, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants