Skip to content

fix(streams): use event-based reconnection in mdns-ws provider#2514

Open
dirkwa wants to merge 1 commit intoSignalK:masterfrom
dirkwa:fix-mdns-ws-reconnection
Open

fix(streams): use event-based reconnection in mdns-ws provider#2514
dirkwa wants to merge 1 commit intoSignalK:masterfrom
dirkwa:fix-mdns-ws-reconnection

Conversation

@dirkwa
Copy link
Contributor

@dirkwa dirkwa commented Mar 24, 2026

Summary

The mdns-ws WebSocket provider failed to reconnect when the remote server was temporarily unreachable (e.g. ENETUNREACH during a simultaneous reboot of both devices).

connectClient() relied on the one-shot Promise returned by client.connect(). When the initial connection failed, the Promise rejected and the .then() block — which sets up provider status, subscriptions, and remoteSelf context mapping — never executed. Even though the underlying @signalk/client Connection successfully reconnected later via its internal backOffAndReconnect() mechanism, the setup logic was skipped permanently.

The fix replaces the Promise-based pattern with persistent event listeners:

  • client.on('connect') runs on every successful connection (initial + reconnections), ensuring subscriptions and provider status are always set up
  • client.on('disconnect') updates provider status when the connection drops
  • client.on('error') reports connection errors to the dashboard

Testing

Automated tests — 4 new integration tests in mdns-ws.test.ts using a real WebSocket server:

  • Provider status set on successful connection
  • Provider error set on connection failure (unreachable port)
  • Disconnect detected when server closes
  • Delta data flows through the stream with correct $source annotation

Manual tests against a live Signal K server (localhost:4000):

  • Verified connect event fires on initial connection and updates provider status
  • Verified socket kill triggers disconnect event, followed by automatic reconnection with a second connect event
  • Verified connection to an unreachable port generates error events with exponential backoff retries (250ms → 500ms → 750ms → 1000ms), confirming the client keeps retrying until the remote becomes available

fixes #2513

connectClient() relied on the one-shot Promise from client.connect().
When the initial connection failed (e.g. ENETUNREACH because the remote
device hasn't booted yet), the Promise rejected and the setup logic
(provider status, subscriptions, remoteSelf mapping) never ran — even
after the underlying @signalk/client Connection successfully reconnected.

Switch from Promise-based (.then/.catch) to persistent event listeners:
- client.on('connect') fires on every successful connection, not just
  the first, ensuring subscriptions and status are always set up
- client.on('disconnect') updates provider status on connection loss
- client.on('error') reports connection errors to the dashboard

fixes SignalK#2513
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.

BUG: reconnection issue: a cerbo connected to my sk server

1 participant