From 1379d0b76b5b4734f2f402333249318ced2019bf Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Sat, 23 Dec 2023 01:40:53 +0800 Subject: [PATCH] Improve reconnection events, add RoomAttemptReconnectEvent. --- example/lib/pages/room.dart | 5 +++++ lib/src/core/engine.dart | 33 +++++++++++++++++++++------------ lib/src/core/room.dart | 22 +++++++++++++++++++--- lib/src/core/signal_client.dart | 3 +-- lib/src/events.dart | 15 +++++++++++++++ lib/src/internal/events.dart | 12 ++++++++++++ lib/src/types/other.dart | 3 ++- 7 files changed, 75 insertions(+), 18 deletions(-) diff --git a/example/lib/pages/room.dart b/example/lib/pages/room.dart index 90f9abf7a..e0137ee38 100644 --- a/example/lib/pages/room.dart +++ b/example/lib/pages/room.dart @@ -94,6 +94,11 @@ class _RoomPageState extends State { ..on((event) { context.showRecordingStatusChangedDialog(event.activeRecording); }) + ..on((event) { + print( + 'Attempting to reconnect ${event.attempt}/${event.maxAttemptsRetry}, ' + '(${event.nextRetryDelaysInMs}ms delay until next attempt)'); + }) ..on((_) => _sortParticipants()) ..on((_) => _sortParticipants()) ..on((_) => _sortParticipants()) diff --git a/lib/src/core/engine.dart b/lib/src/core/engine.dart index dffe549b3..8c4ce2f8f 100644 --- a/lib/src/core/engine.dart +++ b/lib/src/core/engine.dart @@ -228,6 +228,7 @@ class Engine extends Disposable with EventsEmittable { await signalClient.cleanUp(); fullReconnectOnNext = false; + attemptingReconnect = false; clearPendingReconnect(); } @@ -625,8 +626,25 @@ class Engine extends Disposable with EventsEmittable { reconnectStart = DateTime.now(); } + if (reconnectAttempts! >= _reconnectCount) { + logger.fine('reconnectAttempts exceeded, disconnecting...'); + _isClosed = true; + await cleanUp(); + + events.emit(EngineDisconnectedEvent( + reason: DisconnectReason.reconnectAttemptsExceeded, + )); + return; + } + var delay = defaultRetryDelaysInMs[reconnectAttempts!]; + events.emit(EngineAttemptReconnectEvent( + attempt: reconnectAttempts! + 1, + maxAttempts: _reconnectCount, + nextRetryDelaysInMs: delay, + )); + clearReconnectTimeout(); logger.fine( 'WebSocket reconnecting in $delay ms, retry times $reconnectAttempts'); @@ -656,15 +674,6 @@ class Engine extends Disposable with EventsEmittable { fullReconnectOnNext = true; } - if (reconnectAttempts! >= _reconnectCount) { - logger.fine('reconnectAttempts exceeded, disconnecting...'); - events.emit(EngineDisconnectedEvent( - reason: DisconnectReason.connectionClosed, - )); - await cleanUp(); - return; - } - try { attemptingReconnect = true; @@ -704,7 +713,7 @@ class Engine extends Disposable with EventsEmittable { } else { logger.fine('attemptReconnect: disconnecting...'); events.emit(EngineDisconnectedEvent( - reason: DisconnectReason.connectionClosed, + reason: DisconnectReason.disconnected, )); await cleanUp(); } @@ -718,7 +727,7 @@ class Engine extends Disposable with EventsEmittable { return; } - events.emit(const EngineResumingEvent()); + events.emit(const EngineReconnectingEvent()); // wait for socket to connect rtc server await signalClient.connect( @@ -915,7 +924,7 @@ class Engine extends Disposable with EventsEmittable { }) ..on((event) async { logger.fine('Signal disconnected ${event.reason}'); - if (event.reason == DisconnectReason.connectionClosed && !_isClosed) { + if (event.reason == DisconnectReason.disconnected && !_isClosed) { await handleDisconnect(ClientDisconnectReason.signal); } else { events.emit(EngineDisconnectedEvent( diff --git a/lib/src/core/room.dart b/lib/src/core/room.dart index 9f5359c0d..e3b4a3e69 100644 --- a/lib/src/core/room.dart +++ b/lib/src/core/room.dart @@ -13,6 +13,7 @@ // limitations under the License. import 'dart:async'; +import 'dart:math'; import 'package:flutter/foundation.dart'; @@ -408,11 +409,26 @@ class Room extends DisposableChangeNotifier with EventsEmittable { await _sendSyncState(); notifyListeners(); }) - ..on((event) async { - await _cleanUp(); - events.emit(RoomDisconnectedEvent(reason: event.reason)); + ..on((event) async { + events.emit(RoomAttemptReconnectEvent( + attempt: event.attempt, + maxAttemptsRetry: event.maxAttempts, + nextRetryDelaysInMs: event.nextRetryDelaysInMs, + )); notifyListeners(); }) + ..on((event) async { + if (!engine.fullReconnectOnNext && + ![ + DisconnectReason.signalingConnectionFailure, + DisconnectReason.joinFailure, + DisconnectReason.noInternetConnection + ].contains(event.reason)) { + await _cleanUp(); + events.emit(RoomDisconnectedEvent(reason: event.reason)); + notifyListeners(); + } + }) ..on( (event) => _onEngineActiveSpeakersUpdateEvent(event.speakers)) ..on(_onDataMessageEvent) diff --git a/lib/src/core/signal_client.dart b/lib/src/core/signal_client.dart index a492141a7..10536ca2e 100644 --- a/lib/src/core/signal_client.dart +++ b/lib/src/core/signal_client.dart @@ -340,8 +340,7 @@ class SignalClient extends Disposable with EventsEmittable { return; } _connectionState = ConnectionState.disconnected; - events.emit( - SignalDisconnectedEvent(reason: DisconnectReason.connectionClosed)); + events.emit(SignalDisconnectedEvent(reason: DisconnectReason.disconnected)); } void _sendPing() { diff --git a/lib/src/events.dart b/lib/src/events.dart index e2b25d0b0..f18664143 100644 --- a/lib/src/events.dart +++ b/lib/src/events.dart @@ -66,6 +66,21 @@ class RoomReconnectingEvent with RoomEvent { String toString() => '${runtimeType}()'; } +/// report the number of attempts to reconnect to the room. +class RoomAttemptReconnectEvent with RoomEvent { + final int attempt; + final int maxAttemptsRetry; + final int nextRetryDelaysInMs; + const RoomAttemptReconnectEvent({ + required this.attempt, + required this.maxAttemptsRetry, + required this.nextRetryDelaysInMs, + }); + + @override + String toString() => '${runtimeType}()'; +} + /// Connection to room is re-established. All existing state is preserved. /// Emitted by [Room]. class RoomReconnectedEvent with RoomEvent { diff --git a/lib/src/internal/events.dart b/lib/src/internal/events.dart index e93ef23ab..5e6a34b51 100644 --- a/lib/src/internal/events.dart +++ b/lib/src/internal/events.dart @@ -172,6 +172,18 @@ class EngineFullRestartingEvent with InternalEvent, EngineEvent { const EngineFullRestartingEvent(); } +@internal +class EngineAttemptReconnectEvent with InternalEvent, EngineEvent { + int attempt; + int maxAttempts; + int nextRetryDelaysInMs; + EngineAttemptReconnectEvent({ + required this.attempt, + required this.maxAttempts, + required this.nextRetryDelaysInMs, + }); +} + @internal class EngineRestartedEvent with InternalEvent, EngineEvent { const EngineRestartedEvent(); diff --git a/lib/src/types/other.dart b/lib/src/types/other.dart index 615d331b5..28ea642da 100644 --- a/lib/src/types/other.dart +++ b/lib/src/types/other.dart @@ -84,9 +84,10 @@ enum DisconnectReason { roomDeleted, stateMismatch, joinFailure, - connectionClosed, + disconnected, signalingConnectionFailure, noInternetConnection, + reconnectAttemptsExceeded, } /// The reason why a track failed to publish.