fix(sports): stop has_live_content() flooding the log during live games - #241
Conversation
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
📝 WalkthroughWalkthroughBoth 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. ChangesScoreboard live-content logging
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 32 |
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
There was a problem hiding this comment.
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 winInclude active celebrations in the throttled state log.
has_live_content()returnsTruefor an active celebration before this block, at Lines 1801-1804. That path does not update_last_live_content_stateor_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 winUse the shared cache for
FavoriteTeamChecknetwork I/O.Both managers create
FavoriteTeamCheckwithoutself.cache_manager, and_fetch_teams()/_schedule_note()call ESPN APIs directly viarequests. Cache these responses through the plugin’s shared cache usingcache_managerin 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
📒 Files selected for processing (7)
plugins.jsonplugins/baseball-scoreboard/CHANGELOG.mdplugins/baseball-scoreboard/manager.pyplugins/baseball-scoreboard/manifest.jsonplugins/football-scoreboard/CHANGELOG.mdplugins/football-scoreboard/manager.pyplugins/football-scoreboard/manifest.json
🚧 Files skipped from review as they are similar to previous changes (1)
- plugins/football-scoreboard/CHANGELOG.md
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" is harmless for an occasional caller and ruinous for a per-frame one.
Measured on hardware
A 512x64 device with nine live MLB games:
has_live_contentlines/minIt buried every other message and put needless journald writes on the render path. The tell-tale line, note the answer is
Falsethe entire time — the per-league lines fire regardless of what the function returns: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:
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;baseball-scoreboard1.20.3 → 1.20.4,football-scoreboard2.9.3 → 2.9.4.Verification
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;Falsestill throttled. 4/4 pass each.origin/main(missing config template, missing font, a config-reload assertion, a test-mode exception, adaptive-layout and dynamic-duration).Note for the sports unification
The same copy-pasted throttle block is in
hockey-scoreboard(manager.py:2117) andbasketball-scoreboard(manager.py:1440). Those are milder — only the summary bypasses the throttle onTrue, 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 ontosrc/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
Releases