Skip to content

fix(vegas): keep plugin data and visuals fresh during Vegas scroll mode#291

Merged
ChuckBuilds merged 2 commits intomainfrom
fix/vegas-plugin-updates
Mar 21, 2026
Merged

fix(vegas): keep plugin data and visuals fresh during Vegas scroll mode#291
ChuckBuilds merged 2 commits intomainfrom
fix/vegas-plugin-updates

Conversation

@ChuckBuilds
Copy link
Copy Markdown
Owner

@ChuckBuilds ChuckBuilds commented Mar 21, 2026

Summary

  • Background update thread: Adds a non-blocking background thread in the Vegas coordinator that ticks run_scheduled_updates() every ~1s, so ESPN/API plugins refresh data without stalling the 125 FPS scroll
  • Update notification bridge: New _tick_plugin_updates_for_vegas() in display controller detects which plugins actually updated and notifies Vegas via mark_plugin_updated()
  • Scroll cache invalidation: Clears scroll_helper.cached_image on updated plugins so scroll-based plugins (stocks, news, odds-ticker, leaderboard, text-display) rebuild visuals from fresh data
  • Fallback path fix: _capture_display_content() now calls plugin.update() first (ESPN pattern), falling back to update_data() for legacy plugins
  • Thread safety: Background thread is drained on Vegas stop and at end of each iteration via _drain_update_thread() to prevent races with the main loop's own update tick

Test plan

  • Run existing test suite (pytest tests/)
  • Enable Vegas mode with ESPN plugins (baseball, football, etc.) on RPi
  • Verify plugin data refreshes during Vegas scroll (check logs for "Vegas update tick: N plugin(s) updated")
  • Verify scroll-based plugins (stocks, news, odds-ticker) show updated visuals after data refresh
  • Verify no scroll stutter during API calls (updates run in background thread)
  • Verify normal rotation mode is unaffected (changes are Vegas-only paths)
  • Verify clean Vegas stop/restart with no thread warnings in logs

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Plugin updates now run automatically on a periodic schedule during Vegas mode playback, keeping content fresh.
    • Enhanced plugin refresh handling with improved fallback logic.
  • Bug Fixes

    • Fixed stale cached plugin displays by invalidating scroll cache during content updates.

Plugins using ESPN APIs and other data sources were not updating during
Vegas mode because the render loop blocked for 60-600s per iteration,
starving the scheduled update tick. This adds a non-blocking background
thread that runs plugin updates every ~1s during Vegas mode, bridges
update notifications to the stream manager, and clears stale scroll
caches so all three content paths (native, scroll_helper, fallback)
reflect fresh data.

- Add background update tick thread in Vegas coordinator (non-blocking)
- Add _tick_plugin_updates_for_vegas() bridge in display controller
- Fix fallback capture to call update() instead of only update_data()
- Clear scroll_helper.cached_image on update for scroll-based plugins
- Drain background thread on Vegas stop/exit to prevent races

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 21, 2026

Warning

Rate limit exceeded

@ChuckBuilds has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 12 minutes and 56 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 46ff9def-5eac-45e3-b16b-c6d66ccc4dc2

📥 Commits

Reviewing files that changed from the base of the PR and between 22dcff0 and 716e4e3.

📒 Files selected for processing (2)
  • src/vegas_mode/coordinator.py
  • src/vegas_mode/plugin_adapter.py
📝 Walkthrough

Walkthrough

The changes introduce a periodic plugin update mechanism in Vegas mode that detects plugin state changes, invalidates scroll caches, and refreshes content. This involves wiring callback support into the coordinator loop, adding background thread execution with interval throttling, and updating the plugin adapter and stream manager to handle cache invalidation.

Changes

Cohort / File(s) Summary
Vegas Coordinator Infrastructure
src/vegas_mode/coordinator.py
Added set_update_tick() method to register periodic update callbacks with configurable intervals (minimum 0.5s). Implemented background thread execution via _run_update_tick_background() and draining logic via _drain_update_thread(). Modified run_iteration() with try/finally to ensure thread cleanup, and updated stop() to drain pending updates.
Display Controller Update Tick
src/display_controller.py
Added _tick_plugin_updates_for_vegas() method that snapshots plugin state, invokes scheduled updates, detects plugin ID changes, and logs updated plugins. Wired this method into the Vegas coordinator with 1.0s interval.
Plugin Adapter Cache Invalidation
src/vegas_mode/plugin_adapter.py
Added invalidate_plugin_scroll_cache() public method to clear stale scroll visuals. Modified fallback refresh sequence to prefer plugin.update() over plugin.update_data() when available.
Stream Manager Integration
src/vegas_mode/stream_manager.py
Modified process_updates() to invalidate plugin-specific scroll helper cache after standard cache invalidation and before content refetching for each updated plugin.

Sequence Diagram

sequenceDiagram
    participant VegasLoop as Vegas Render Loop
    participant Coordinator as VegasModeCoordinator
    participant DisplayCtrl as DisplayController
    participant PluginMgr as PluginManager
    participant StreamMgr as StreamManager
    participant PluginAdapter as PluginAdapter
    
    loop Each Render Iteration (Vegas Mode)
        VegasLoop->>Coordinator: run_iteration()
        Coordinator->>Coordinator: _drain_update_thread()
        activate Coordinator
        Note over Coordinator: Drain accumulated<br/>update results
        deactivate Coordinator
        
        alt Update thread interval elapsed
            Coordinator->>DisplayCtrl: _tick_plugin_updates_for_vegas() [background]
            activate DisplayCtrl
            DisplayCtrl->>PluginMgr: Snapshot plugin_last_update
            DisplayCtrl->>PluginMgr: Invoke _tick_plugin_updates()
            DisplayCtrl->>DisplayCtrl: Detect changed plugin IDs
            DisplayCtrl-->>Coordinator: Return changed plugin IDs
            deactivate DisplayCtrl
        end
        
        Coordinator->>StreamMgr: process_updates(plugin_ids)
        activate StreamMgr
        loop For each updated plugin
            StreamMgr->>PluginAdapter: invalidate_cache(plugin_id)
            StreamMgr->>PluginAdapter: invalidate_plugin_scroll_cache(plugin, plugin_id)
            activate PluginAdapter
            PluginAdapter->>PluginAdapter: Clear scroll_helper.cached_image
            deactivate PluginAdapter
            StreamMgr->>StreamMgr: _fetch_plugin_content(plugin_id)
        end
        deactivate StreamMgr
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main purpose: fixing Vegas scroll mode plugin updates by keeping both data and visuals fresh. It directly relates to the core changes across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/vegas-plugin-updates

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/vegas_mode/coordinator.py`:
- Around line 343-351: STATIC pauses currently skip the update-tick block
because the early continue after handling a static pause prevents
run_scheduled_updates from being called; update the logic in coordinator.py
around _check_static_plugin_trigger / _handle_static_pause so that after a
static pause is handled you still drive the background updater: remove the
unconditional continue or refactor the static-pause branch to repeatedly call
run_scheduled_updates (and any timing/tick advancement) while waiting for the
static pause to finish, then consume the segment via
stream_manager.get_next_segment() and proceed normally; ensure the same change
is applied to the analogous block covering lines 381-405.
- Around line 543-555: _drain_update_thread currently only logs on timeout but
doesn't signal the caller; change its contract to return a boolean (or otherwise
set a clear flag) so callers can detect a still-running background updater.
Specifically, update the method _drain_update_thread(self, timeout: float = 2.0)
to return True if the thread is still alive after join(timeout) and False if it
finished (and clear/self._update_thread = None when finished); then update
DisplayController.run() (and any caller that expects to resume
_tick_plugin_updates or call run_scheduled_updates) to check the return value
and suppress scheduling/ticks while True is returned (or while the flag
indicates the worker is alive). Ensure references to _update_thread.is_alive()
and _tick_plugin_updates / run_scheduled_updates behavior are updated
accordingly.

In `@src/vegas_mode/plugin_adapter.py`:
- Around line 411-426: The Vegas fetch path must not call plugin.update()
because process_updates() already triggers background refreshes; remove the
synchronous plugin.update() invocation in the fallback branch (the block that
checks has_update) and instead only attempt the non-blocking fallback pattern by
checking and calling plugin.update_data() when present; update the logging
around plugin_id to reflect that update() is intentionally skipped and that only
update_data() will be used as the fallback so we don't perform a second
synchronous refresh on the render/prefetch thread.
- Around line 613-616: The code only clears scroll_helper.cached_image, leaving
cached_array and total_scroll_width stale; replace resetting cached_image with a
call to scroll_helper.clear_cache() so the full ScrollHelper state
(cached_image, cached_array, total_scroll_width, etc.) is reset, and update the
debug log to reflect that the full cache was cleared (use plugin_id in the log
as before).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 19d7d602-c1fa-49fc-a52b-5f37728fd5df

📥 Commits

Reviewing files that changed from the base of the PR and between c8737d1 and 22dcff0.

📒 Files selected for processing (4)
  • src/display_controller.py
  • src/vegas_mode/coordinator.py
  • src/vegas_mode/plugin_adapter.py
  • src/vegas_mode/stream_manager.py

- Extract _drive_background_updates() helper and call it from both the
  render loop and the static-pause wait loop so plugin data stays fresh
  during static pauses (was skipped by the early `continue`)
- Remove synchronous plugin.update() from the fallback capture path;
  the background update tick already handles API refreshes so the
  content-fetch thread should only call lightweight update_data()
- Use scroll_helper.clear_cache() instead of just clearing cached_image
  so cached_array, total_scroll_width and scroll_position are also reset

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ChuckBuilds ChuckBuilds merged commit 8391832 into main Mar 21, 2026
1 check passed
5ymb01 added a commit to 5ymb01/LEDMatrix that referenced this pull request Mar 23, 2026
Reconcile squash-merged PRs (ChuckBuilds#277, ChuckBuilds#290, ChuckBuilds#291) from upstream.
Resolve conflict in vegas_mode/coordinator.py: keep both the
interrupt check callback (upstream) and inline cycle restart (Dev).

Co-Authored-By: 5ymb01 <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5ymb01 added a commit to 5ymb01/LEDMatrix that referenced this pull request Mar 23, 2026
Reconcile squash-merged PRs (ChuckBuilds#277, ChuckBuilds#290, ChuckBuilds#291) from upstream.
Resolve conflict in vegas_mode/coordinator.py: keep both the
interrupt check callback (upstream) and inline cycle restart (wip).

Co-Authored-By: 5ymb01 <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant