Skip to content

Commit

Permalink
fix(realtime_client): No exception is thrown when connection is close…
Browse files Browse the repository at this point in the history
…d. (#620)

* fix: realtime throwing error when connection is closed

* fix: adjust test case to align with js client
  • Loading branch information
dshukertjr authored Sep 10, 2023
1 parent c155f69 commit 64b8b96
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
2 changes: 1 addition & 1 deletion packages/realtime_client/lib/src/realtime_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ class RealtimeChannel {
/// Registers a callback that will be executed when the channel encounteres an error.
void onError(void Function(String?) callback) {
onEvents(ChannelEvents.error.eventName(), ChannelFilter(),
(reason, [ref]) => callback(reason.toString()));
(reason, [ref]) => callback(reason?.toString()));
}

RealtimeChannel on(
Expand Down
28 changes: 26 additions & 2 deletions packages/realtime_client/lib/src/realtime_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@ typedef RealtimeDecode = void Function(
void Function(dynamic result) callback,
);

/// Event details for when the connection closed.
class RealtimeCloseEvent {
/// Web socket protocol status codes for when a connection is closed.
///
/// The full list can be found at the following:
///
/// https://datatracker.ietf.org/doc/html/rfc6455#section-7.4
final int code;

/// Connection closed reason sent from the server
///
/// https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6
final String? reason;

const RealtimeCloseEvent({
required this.code,
required this.reason,
});
}

class RealtimeClient {
String? accessToken;
List<RealtimeChannel> channels = [];
Expand Down Expand Up @@ -387,13 +407,17 @@ class RealtimeClient {

/// communication has been closed
void _onConnClose() {
final event = conn?.closeReason ?? '';
final statusCode = conn?.closeCode;
RealtimeCloseEvent? event;
if (statusCode != null) {
event = RealtimeCloseEvent(code: statusCode, reason: conn?.closeReason);
}
log('transport', 'close', event);

/// SocketStates.disconnected: by user with socket.disconnect()
/// SocketStates.closed: NOT by user, should try to reconnect
if (connState == SocketStates.closed) {
_triggerChanError(event);
_triggerChanError();
reconnectTimer.scheduleTimeout();
}
if (heartbeatTimer != null) heartbeatTimer!.cancel();
Expand Down
4 changes: 2 additions & 2 deletions packages/realtime_client/test/mock_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ void main() {
});

test("correct CHANNEL_ERROR data on heartbeat timeout", () async {
final subscribeCallback = expectAsync2((event, [data]) {
final subscribeCallback = expectAsync2((event, [error]) {
if (event == "CHANNEL_ERROR") {
expect(data, "heartbeat timeout");
expect(error, isNull);
} else {
expect(event, "CLOSED");
}
Expand Down

0 comments on commit 64b8b96

Please sign in to comment.