Action-Cable-Swift icon indicating copy to clipboard operation
Action-Cable-Swift copied to clipboard

addOnMessage Calls multiple times for a single broadcast

Open ankitpoplify opened this issue 3 years ago • 2 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()
    }
}

`

ankitpoplify avatar Jun 23 '22 18:06 ankitpoplify

@nerzh Can you please help me with this?

ankitpoplify avatar Jun 23 '22 18:06 ankitpoplify

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()

ConfusedVorlon avatar Apr 20 '23 19:04 ConfusedVorlon