Skip to content

Stop MidiStatus polling forever - #107

Merged
ctoth merged 2 commits into
masterfrom
agent/issue-101-midistatus-poll
Aug 12, 2026
Merged

Stop MidiStatus polling forever#107
ctoth merged 2 commits into
masterfrom
agent/issue-101-midistatus-poll

Conversation

@daiverd

@daiverd daiverd commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #101

The 2 s interval called loadDevices() unconditionally for the life of the MIDI panel and compared connection state by double JSON.stringify — against a stale closure, so the comparison could also be wrong.

Changes

  • The poll's only unique job is catching virtual-synth availability (injected into getOutputDevices() when virtualMidiService.initialized; JZZ emits no change event for it). It now stops permanently as soon as the synth is observed — which loadDevices() itself triggers, so in practice one or two ticks — or after 60 s.
  • Refresh work is skipped while document.hidden, but initialization and timeout completion checks still clear the interval while hidden; one catch-up refresh runs on visibilitychange.
  • Connection state changes use a shallow field compare over the six connectionStatus fields via functional setState (fixes the stale closure), and are also refreshed from the existing onDeviceChange callback so auto-reconnect status stays event-driven.
  • MidiService records hardware removals before notifying device-change listeners, so callbacks observe the completed disconnection state.
  • Effect cleanup clears the interval and the visibility listener.
  • Regression tests cover callback-visible device removal state and hidden-tab timeout cleanup.

Hardware device arrival/removal remains event-driven via midiService.onDeviceChange.

Full suite 1065/1065 green; tsc --noEmit and the production build are clean.

🤖 Generated with Claude Code

The 2 s interval called loadDevices() unconditionally for the life of
the panel and double-stringified connection state to compare it, even
though hardware device changes are already delivered event-driven via
midiService.onDeviceChange.

The poll's only unique job is catching virtual synth initialization,
which JZZ never reports, so it now stops as soon as the synth is
observed (or after 60 s), skips ticks while the tab is hidden with a
catch-up refresh on visibilitychange, and connection state changes are
detected with a shallow field compare against the live previous state
(fixing a stale-closure comparison) and refreshed from the device
change callback as well.

Fixes #101

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ctoth
ctoth merged commit e8de18a into master Aug 12, 2026
1 check passed
github-actions Bot pushed a commit that referenced this pull request Aug 12, 2026
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.

MidiStatus: 2s poll calls loadDevices() unconditionally and double-stringifies to compare

2 participants