Skip to content

Emit a single disconnected event when connecting fails#1126

Merged
hiroshihorie merged 2 commits into
mainfrom
hiroshi/certificate-pinning-event-dedup
Jul 7, 2026
Merged

Emit a single disconnected event when connecting fails#1126
hiroshihorie merged 2 commits into
mainfrom
hiroshi/certificate-pinning-event-dedup

Conversation

@hiroshihorie

Copy link
Copy Markdown
Member

Summary

Follow-up to #1065. Ensures the SDK emits exactly one RoomDisconnectedEvent per failed connection attempt.

Previously a failed initial connect produced two EngineDisconnectedEvents, and therefore two RoomDisconnectedEvents and two room cleanups:

  1. The signal client emits SignalDisconnectedEvent(signalingConnectionFailure) while connect() is failing (the validate path has done this since Improve reconnect logic for websocket #406, and the certificate pinning path in Certificate pinning #1065 follows the same pattern), which the engine relayed as EngineDisconnectedEvent.
  2. Engine.connect's catch then emits EngineDisconnectedEvent(joinFailure) for the same failure.

Changes

  • Engine.connect's catch is now the single emitter for initial connect failures. It picks the reason by error type: signalingConnectionFailure for CertificatePinningException, joinFailure otherwise.
  • The signalingConnectionFailure relay in the engine's signal listener is removed (with a comment explaining why). During reconnects the engine's reconnect handling already owns disconnect emission, so the relay only ever produced duplicates. This also removes the _isReconnecting/_attemptingReconnect guard that Certificate pinning #1065 added to suppress the relay during reconnects, since there is no longer anything to suppress.
  • SignalDisconnectedEvent at the signal level is unchanged, only the engine-level relay is removed.

Behavior change

Apps listening for RoomDisconnectedEvent now receive one event per failed connect instead of two. The reasons are unchanged for the common case (joinFailure); certificate pinning failures surface as signalingConnectionFailure. Apps that specifically depended on receiving both events for a single failure would see one.

Testing

Added room-level tests through the mock e2e container asserting exactly one RoomDisconnectedEvent per failed initial connect, for both a certificate pinning failure (signalingConnectionFailure) and a generic websocket failure (joinFailure). Both tests fail against the previous code (two events observed) and pass with this change.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment thread lib/src/core/engine.dart Outdated
Comment on lines 271 to 275
events.emit(EngineDisconnectedEvent(
reason: DisconnectReason.joinFailure,
reason: error is CertificatePinningException
? DisconnectReason.signalingConnectionFailure
: DisconnectReason.joinFailure,
));

@devin-ai-integration devin-ai-integration Bot Jul 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Region fallback in Room.connect may emit a spurious RoomDisconnectedEvent before retrying

When Room.connect catches a WebSocketException or ConnectException from the first engine.connect call and falls back to a regional URL (room.dart:340-366), the engine's catch block at lib/src/core/engine.dart:271-275 has already emitted an EngineDisconnectedEvent. The room's listener at lib/src/core/room.dart:596-601 converts this into a RoomDisconnectedEvent. If the second engine.connect succeeds, the room ends up having emitted a disconnect event followed by a successful connection — which could confuse listeners. This is a pre-existing issue not introduced by this PR, but since the PR's goal is to ensure a single disconnected event per failure, it may be worth addressing in a follow-up.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Base automatically changed from hiroshi/certificate-pinning to main July 6, 2026 09:00
@hiroshihorie hiroshihorie force-pushed the hiroshi/certificate-pinning-event-dedup branch from c260cba to 11a9f0f Compare July 6, 2026 09:04
devin-ai-integration[bot]

This comment was marked as resolved.

@hiroshihorie hiroshihorie merged commit 051581b into main Jul 7, 2026
18 checks passed
@hiroshihorie hiroshihorie deleted the hiroshi/certificate-pinning-event-dedup branch July 7, 2026 09:08
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.

2 participants