feat(plugins): request_on_demand() / end_on_demand() -- plugins ask for the screen in-process - #768
Conversation
…or the screen in-process Four plugins (birdnet-go, mqtt-notifications, on-air, pomodoro-timer) take the screen by writing the display_on_demand_request mailbox, which the display reads once a second while the control socket is up and which stage 5 removes. This is the in-process way in that stage needed. - BasePlugin.request_on_demand(mode=None, duration=None, pinned=False) and end_on_demand(), safe from any thread, go through PluginManager to DisplayController.submit_plugin_on_demand, which only queues (at most 32) and wakes the render thread through ControlServer.wake(). The render thread applies them in _drain_control_commands, after socket commands, through _handle_on_demand_request, so they land within a frame; without a socket, on the next pending-changes pass. - A plugin's stop ends only its own session; a mailbox stop still ends any. - Both answer the request id, or None with no display in the process (web interface, check_plugin.py), a full queue, or a mock manager -- a plugin's cue to write the mailbox, which the display still reads. - docs/PLUGIN_API_REFERENCE.md documents the hasattr pattern for plugins that must keep working on older cores; IPC_CONTROL_SOCKET.md and the CHANGELOG are updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 47 minutes. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (1)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (8)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughPlugins can submit on-demand display start and stop requests through ChangesPlugin on-demand requests
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant BasePlugin
participant PluginManager
participant DisplayController
participant ControlServer
participant RenderThread
BasePlugin->>PluginManager: Submit start or stop request
PluginManager->>DisplayController: Submit request with plugin source
DisplayController->>ControlServer: Wake render loop when available
RenderThread->>DisplayController: Drain queued plugin requests
DisplayController->>RenderThread: Apply requests through on-demand handler
Merge Risk: ⚪ Minimal · up to Plugin requests without a control socket may wait until the next pending-changes pass, as documented. No issue identified here prevents merging after normal checks. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to The change reuses existing display controls and narrows plugin-initiated stops. However, sustained plugin requests can monopolize request processing and delay user stop or recovery commands: limiting queue size does not limit processing time. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 35.82% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 67 functions across 5 files. (3 skipped: 3 unsupported.) ✨ Finishing Touches 💡 1📝 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 | 25 |
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.
Tests and the golden traces stand in simpler plugin managers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Full suite on Windows (Python 3.14, Pillow 12.3), this branch at 5f80b93 against an origin/main clone at 5a7893b:
🤖 Generated with Claude Code |
Summary
Stage 5 of the control socket (
docs/IPC_CONTROL_SOCKET.md) needs an in-process way for plugins to ask for the screen before thedisplay_on_demand_requestmailbox can go. Four plugins write that mailbox today (birdnet-go, mqtt-notifications, on-air, pomodoro-timer), and since #765 the display reads it only once a second while the socket is up.API
BasePlugin->PluginManager.request_on_demand(plugin_id, ...)/end_on_demand(plugin_id)->DisplayController.submit_plugin_on_demand(request), wired withPluginManager.set_on_demand_handler()before any plugin loads.submit_plugin_on_demandonly queues: an in-memory deque behind a lock, at most 32, and a full queue is refused. It wakes the render thread through the socket's flag (ControlServer.wake(), new). The render thread applies the queue in_drain_control_commands, after socket commands, through the same_handle_on_demand_request. So a request lands within a frame, and on the next pending-changes pass (about 0.25 s) without a socket.source: 'plugin'. It never reads or deletes the mailbox file.Nonewhen there is no display in the process (the web interface,check_plugin.py), when the queue is full, or when the manager answered something other than a string (a test'sMagicMock).Noneis the plugin's cue to write the mailbox, which the display still reads.ValueError: a non-stringmode, or a non-numeric or boolduration. A non-positive or non-finitedurationmeans no limit, as on the mailbox path.Older cores:
docs/PLUGIN_API_REFERENCE.md("On-demand display") documents thehasattrfeature-detection pattern with the mailbox fallback, and says to keepledmatrix_min_versionunchanged.Docs: PLUGIN_API_REFERENCE.md (BasePlugin and Plugin Manager sections), IPC_CONTROL_SOCKET.md (mailbox table, new "Plugins in the display process" section, stage 5), CHANGELOG under Unreleased.
Tests
test/test_plugin_on_demand_api.py, 36 tests, covering:PluginManager;ControlServer's wait, and the no-socket wait;MagicMockcases;hasattrpattern;from_mailbox, the stop ownership guard,wake(), the pending check, the drain call, the no-socket wait, the wiring, the queue limit, FIFO order, the accepted-to-None mapping, duration normalisation, the stop'splugin_id,pinnedpass-through, andControlServer.wakeitself.scripts/check_types.py) shows only thesrc/common/fetch_service.pyunused-ignore that origin/main shows on this machine. The touched non-ratchet modules have 253 errors, the same count as main.The plugins PR follows once this merges.
🤖 Generated with Claude Code
Summary by CodeRabbit