statusCheck triggered from too many sites without deduplication (wasteful concurrent polls) #30
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
statusCheckis started from four different locations:toggleProcess.onExitedexitNodeProcess.onExiteddetectClipboard.onExitedOn startup and after operations, multiple concurrent status polls can be launched. While Quickshell may queue them, the pattern is wasteful and risks interleaved state updates.
Impact
Unnecessary process invocations and potential for unpredictable state-update ordering on every toggle, exit-node change, or clipboard detection.
FYI from cross-model audit (claude-sonnet-4-6):
statusCheckis started from multiple sites (timer, toggleProcess.onExited, exitNodeProcess.onExited, detectClipboard.onExited) without anyif (statusCheck.running) returnguard. This is the concrete mechanism behind the over-triggering and potential concurrent polls described in this issue.See also #15 (no guard against concurrent toggleProcess / exitNodeProcess invocations) — same pattern of missing
.runningguards on Process components.Proposed Path Forward — Polling Optimization & Startup Race
Resolves: #30 (statusCheck from too many sites without dedup), #33 (aggressive 5s polling when popout closed), #26 (timer fires before detectClipboard completes)
Overview
These three issues are about when and how often
statusCheckruns. #30 is about deduplication of concurrent triggers, #33 is about stopping polling when the popout is closed, and #26 is about the startup race between the timer anddetectClipboard. All three are solved by restructuring the timer lifecycle and adding a dedup guard.Plan
Step 1 — Popout-aware timer (fixes #33)
Bind the Timer's
runningproperty to the popout's visibility state. In Quickshell'sPluginComponent, the popout is open when the user left-clicks the icon. Use thepopoutOpensignal or a visibility binding to start/stop the timer:Timer.running = true, fire one immediatestatusCheckfor fresh dataTimer.running = falseThis eliminates the 5-second polling when the widget is not in use. The icon pill still reflects the last-known state (it doesn't need live updates when closed).
Step 2 — Deduplication guard (fixes #30)
Add a guard in each location that triggers
statusCheck.running = true:This prevents restarting a process that's already mid-execution. The four trigger sites are:
Each becomes a no-op if
statusCheckis already running. This is safe becausestatusCheckis not a long-lived process — it runs, exits, and the next trigger will start it again.Step 3 — Startup sequencing (fixes #26)
Move the Timer's
running: trueto be triggered bydetectClipboard.onExitedinstead of beingtrueat declaration. Change:Then in
detectClipboard.onExited, after triggering the initialstatusCheck, also start the timer:This ensures
clipboardCmdis populated before the first status poll runs. The initialstatusChecktriggered bydetectClipboard.onExitedalready exists, so the timer just needs to start after it.Success Criteria
statusCheck.running = trueis guarded by!statusCheck.runningat all four trigger sites.detectClipboard.onExitedfires, not at component initialization.AFK Classification
AFK. Pure QML logic changes. The agent can verify the control flow statically. The timer-popout binding may require checking Quickshell's API for the correct signal/property name (may need to grep the Quickshell source or docs for
popoutOpenor equivalent). If the exact API name is unclear, the agent can make a reasonable guess and note it for HITL verification.Files Modified
tailscalectl/TailscaleWidget.qml— Timer configuration, all four statusCheck trigger sites, detectClipboard.onExitedAlso resolves: #33, #26
The general idea look okay. But check your detectClipboard.onExited behavior before implementing your plan. #12's plan is to completely refactor that behavior. #12's plan may be implemented first.
Added running guard + dedup flag on statusCheck to prevent overlapping polls. Merged to vibes.
Resolved via merge
daab237. The plugin is confirmed working by @jtmorris. Human code review required before merging to testing.