Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: [DRGO-1410]: ramin/refactor_ws_connection_management #351

Merged
merged 25 commits into from
Dec 4, 2024

Conversation

ramin-deriv
Copy link
Contributor

@ramin-deriv ramin-deriv commented Nov 7, 2024

There are two issues that this PR addresses:

  1. Frequent Triggering of Disconnect Event
    Cause: We use both WebSocket channel callbacks (e.g., onDone, onError) and the phone's network status (Wi-Fi, mobile data, VPNs, etc. using connectivity_plus package) to determine connection status. Two of them can happen at the same time causing the ConnectionCubit to try to reconnect and emit a disconnect state causing the Reconnecting dialog to appear frequently.
    Solution: Use the WebSocket channel as the single source of truth for the connection status. By sending periodic pings to the server and checking ping success/failure timeout will confirm whether the connection is active or disconnected (the websocket_channel package that we use supports this out of the box). We can still keep the connectivity_plus and add it in the app itself to inform the user about network availability changes, but we don't interfere WebSocket's connection management with its status changes.

  2. Reduce the time takes to establish the WS connection
    This is the time that it takes to establish WebSocket connection and dismiss the connecting dialog.
    Cause: We currently confirm the WebSocket connection is established upon receiving the first pong response from the WebSocket server. A 5-second timer in ConnectionCubit sends periodic ping messages to the server, but if a ping was recently sent just before calling WebSocket.connect, we might have to wait up to 5 seconds until the next ping, delaying confirmation of the connection.
    Solution: Keep the ConnectionCubit timer only for regular pings when the connection is stable, stopping it upon disconnection. After calling the connect method, we create and start another timer with a shorter interval duration in BinaryApi to send ping requests, allowing us to confirm the connection status more quickly. We apply a exponential back-off strategy for this ping to avoid flooding the server if connecting to websocket fails. (We can even remove the timer in ConnectionCubit if we see it doesn't serve any other purpose)

image

Note: The WebSocketChannel package provides a ready future to indicate when the WebSocket connection is established. Ideally, after calling WebSocket.connect, we would wait for this future to complete before sending or receiving messages. However, this method is unreliable, as we sometimes fail to receive responses after the ready status. Until we find a more reliable way to utilize the ready future, we will continue with the above approach.

@ramin-deriv ramin-deriv changed the title ramin/refactor_ws_connection_management refactor: [DRGO-1410]: ramin/refactor_ws_connection_management Nov 7, 2024
Comment on lines 122 to 126
unawaited(_webSocketChannel?.ready.then((_) {
print('#### Timer started ${DateTime.now()}');
_startConnectionTimer();
}));

Choose a reason for hiding this comment

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

Would it be safer to set this callback before calling IOWebSocketChannel.connect

@ramin-deriv ramin-deriv merged commit 5322528 into deriv-com:master Dec 4, 2024
2 checks passed
@ramin-deriv ramin-deriv deleted the ramin/use_ready_flag branch December 4, 2024 05:39
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.

3 participants