Skip to content

StatePublisher: rateHz 0 removes a subscription; subscriptions removed when their connection has gone - #13

Merged
robdobsn merged 1 commit into
mainfrom
fix/statepub-unsubscribe
Oct 25, 2026
Merged

robdobsn merged 1 commit into
mainfrom
fix/statepub-unsubscribe

Conversation

@robdobsn

Copy link
Copy Markdown
Owner

A WebSocket client that never subscribed was receiving camera frames. Two causes:

  1. rateHz: 0 didn't disable a subscription. It kept it with a rate of 0, so the interval between heartbeat publishes was 0 ms and every check published (as fast as minMs allows). The wiki documents 0 as "disable", and raftjs relies on it: it sends rateHz: 0 on disconnect, and the dashboard's camera panel sends it to stop live view. An update with rateHz 0, or createSubscription() with rate 0, now removes the subscription.
  2. Subscriptions outlived their connection. When a publish found no connection on the channel, the subscription was backed off and kept. A WebSocket channel belongs to a connection slot, so the next client in that slot got the old subscription's publishes without subscribing, and the camera kept capturing frames for it. Now a subscription whose channel reports no connection (a WebSocket slot with no client, BLE with no central connected) is removed. Clients subscribe again when they connect; raftjs does. Channels that never report a lost connection keep their subscriptions, as before: serial, and MQTT (whose subscriptions are created from its config).

Tested

Plant growth board (ESP32-S3, camera) over WebSockets:

After the first client... A new client that never subscribed got (6 s)
unsubscribed with rateHz: 0, then closed before: 23 frames; after: none
closed without unsubscribing before: 7 frames; after: none

A subscribed client still gets frames at its rate: 12 in 6 s at 2 Hz. The board logs loop removed subscription topic Camera channelID 2 (no connection) when a subscription is removed.

Not tested here: a BLE reconnect. raftjs subscribes again on connect, so this shouldn't change anything for it.

🤖 Generated with Claude Code

…d when their connection has gone

- A subscription update (or createSubscription) with rateHz 0 removes the subscription, as documented and as
  raftjs uses it (on disconnect, and the dashboard's camera panel to stop live view). It was kept with a rate of
  0, which made every check a heartbeat, so it published as fast as minMs allowed.
- A subscription whose channel reports no connection when a publish is attempted (a websocket with no client in
  its slot, BLE with no central) is removed, rather than backed off and kept. A websocket channel belongs to a
  connection slot, so the next client in the slot got the old subscription's publishes without subscribing (and a
  camera kept capturing for it). Clients subscribe again when they connect (raftjs does). Channels that don't
  report connections (serial, MQTT) keep theirs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@robdobsn
robdobsn merged commit 1db1c18 into main Oct 25, 2026
1 check passed
@robdobsn
robdobsn deleted the fix/statepub-unsubscribe branch October 25, 2026 21:47
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