nerzh / Action-Cable-Swift

ActionCable is a WebSocket server being released with Rails 5 which makes it easy to add real-time features to your app. This Swift client inspired by "Swift-ActionCableClient", but it not support now and I created Action-Cable-Swift. Also web sockets are now separate from the client.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

addOnMessage Calls multiple times for a single broadcast

ankitpoplify opened this issue · comments

Hello @nerzh , First of all, thanks for an amazing library. I'm facing a strange issue while creating a connection. I'm using WS to create a connection. I followed all the instructions and I'm able to create connections, create/subscribe channels, and receive messages. The only problem I'm facing is whenever I create a connection the connection gets created 3 times/6 times in a row and whenever the server sends a broadcast, I receive it 6 times. Can you please explain what is the issue?
Here is my code:-
`import UIKit
import ActionCableSwift

class ChatsListVC: UIViewController {

//MARK: IB Outlets
var ws: WSS = .init(stringURL: "ws://53b6-2405-201-5009-610f-24fa-6b65-905b-b188.ngrok.io/cable")
var clientOptions: ACClientOptions = .init(debug: true, reconnect: true)
var client: ACClient!
var channelOptions: ACChannelOptions!
var channel: ACChannel!


override func viewDidLoad() {
    super.viewDidLoad()
    self.setupActionCable()
}

func setupActionCable() {
    /// web socket client
    //self.ws = .init(stringURL: "ws://localhost:3001/cable")

    /// action cable client
    //self.clientOptions = .init(debug: false, reconnect: true)
    self.client = .init(ws: ws, options: clientOptions)
    /// on server you can get this with env['HTTP_COOKIE']
    client.headers = ["Authorization": appUser.auth_token!]

    /// make channel
    /// buffering - buffering messages if disconnect and flush after reconnect
    let channelOptions: ACChannelOptions = .init(buffering: true, autoSubscribe: false)
    /// params to subscribe passed inside the identifier dictionary
    let identifier: [String: Any] = ["conversation_id": "2"]
    channel = (client.makeChannel(name: "ConversationChannel", identifier: identifier, options: channelOptions))

    // !!! Make sure that the client and channel objects is declared "globally" and lives while your socket connection is needed

    channel?.addOnSubscribe { (channel, optionalMessage) in
        print(optionalMessage)
    }
    channel?.addOnMessage { (channel, optionalMessage) in
        print(optionalMessage)
    }
    channel?.addOnPing { (channel, optionalMessage) in
        print("ping")
    }
    /// Connect
    client.connect()
    
    client.addOnConnected { (headers) in
        try? self.channel.subscribe()
    }
}

`

@nerzh Can you please help me with this?

I'm seeing the same thing. Only two connections created in my case!

The problem seems to be that if you set options.reconnect, the in the client init, the pingRoundWatcher is started.
It immediately detects that there is no connection, so it tries to connect.
You then call connect again manually.

Ditching the manual connect seems to fix things for me - though I'm worried that the ping watcher might still start multiple connection attempts if the connection latency is non-zero.

I suspect there needs to be a lock of something like 'connectionAttemptInProgress' which stops the pingWatcher from adding a duplicate connection attempt...

just for clarity - the fix in your code above

    /// Connect
   // don't connect manually - the pingWatcher will do it for you!
   // client.connect()