centrifugal / centrifuge-swift

Swift client SDK for bidirectional real-time communication with Centrifugo and Centrifuge-based server over WebSocket
MIT License
49 stars 45 forks source link

Proposal: Add a Method to Reset Reconnect State in Centrifugo Client #106

Open shalom-aviv opened 6 days ago

shalom-aviv commented 6 days ago

Description:

Currently, the Centrifugo client uses an exponential backoff strategy for reconnecting after a disconnection. While this approach is generally effective, it can lead to a suboptimal scenario where:

This situation results in unnecessary delays in reestablishing the connection, even though the network is ready.

Proposed Solutions:

  1. Manual Reconnection:
  1. Introduce a Method to Reset Reconnect State:
    • Add a method to the Centrifugo client that allows resetting the reconnect state and immediately starting a reconnect attempt if necessary.
    • This would simplify handling scenarios where the network connection has been restored, but the client is still in a long backoff phase.

Example of the proposed method:

public class CentrifugeClient {
    //...

    /**
     Reset reconnecting state to initial and schedule reconnect if needed.
     */
    public func resetReconnecting() {
        self.syncQueue.async { [weak self] in
            guard let strongSelf = self else { return }
            strongSelf.reconnectAttempts = 0

            guard strongSelf.reconnectTask != nil else { return }
            strongSelf.scheduleReconnect()
        }
    }

    //...
}

Benefits:

FZambia commented 3 days ago

Thanks for the suggestion @shalom-aviv ! Yep, it's important to have, in centrifuge-js we already react on browser's online/offline events so the connection is quickly re-established upon going online, but other SDKs do not provide hooks for this.

Generally, I am thinking now whether we need a separate method for that, or maybe can have this logic directly in connect method.

The downside of having it directly in the connect though is that it will be required to check whether client is in connecting state before calling connect to not occasionally move disconnected client to the connected state. Pseudocode:

// on online event
if client.state == 'connecting' {
  client.connect()
}

In this perspective having a separate method to resetReconnectingState and not bother about checking client state may be preferred.

WDYT?

shalom-aviv commented 20 hours ago

Thanks for the suggestion @shalom-aviv ! Yep, it's important to have, in centrifuge-js we already react on browser's online/offline events so the connection is quickly re-established upon going online, but other SDKs do not provide hooks for this.

Generally, I am thinking now whether we need a separate method for that, or maybe can have this logic directly in connect method.

The downside of having it directly in the connect though is that it will be required to check whether client is in connecting state before calling connect to not occasionally move disconnected client to the connected state. Pseudocode:

// on online event
if client.state == 'connecting' {
  client.connect()
}

In this perspective having a separate method to resetReconnectingState and not bother about checking client state may be preferred.

WDYT?

I agree that adding logic directly into the connect method could potentially create confusion. The current lifecycle of connection through connect and disconnect is clear and intuitive, and adding an additional behavior for connect—especially one that requires checking the client state—might complicate its usage.

A separate resetReconnectingState method, seems to align better with the existing architecture and provides a clean and explicit way to manage the reconnection logic. Here's why I believe this approach is preferable:

  1. Consistency with Existing Lifecycle:
    The current lifecycle (connect to start, disconnect to stop) remains unchanged. A dedicated method for resetting the reconnection state complements this lifecycle without introducing ambiguity.

  2. Clear and Predictable Behavior:
    The purpose of resetReconnectingState is clear: reset the attempt count and delay to zero, and, if there is a scheduled reconnect attempt, start it immediately. This explicit behavior avoids the need to "peek" into the client's state before calling connect.

  3. Developer-Focused API:
    Developers can use resetReconnectingState in scenarios like restoring network connectivity without having to manage additional checks or worry about accidentally transitioning a client from disconnected to connected.

Here’s how the method could be described:


resetReconnectingState


With this approach, the API remains intuitive and easy to use, while providing flexibility for scenarios where immediate reconnection is required.

WDYT?