Proper EM reconnect support
MmKolodziej opened this issue · comments
Hey,
I've been having trouble while trying to setup proper reconnecting using your gem (using it through action_cable_client, but I believe that's irrelevant). Anyway, event machine supports reconnecting, but the method is not exposed in WebSocket::EventMachine::Client and due to this: eventmachine/eventmachine#218 implementing it is not straight forward.
This is what I've had to do in order to get stable reconnects:
require 'websocket-eventmachine-client'
EventMachine.run do
ws = WebSocket::EventMachine::Client.connect(uri: 'ws://localhost:3000/websocket')
ws.onclose do |code, reason|
puts "Disconnected with status code: #{code}"
EM.add_timer(2) do
EventMachine.reconnect "localhost", 3000, ws
ws.post_init
end
end
end
It should be pretty easy to remember the host and port and implement a simple reconnect method that will take care of firing post_init callback for the user. Let me know if this is something you'd like to see in your gem, I'll prepare a PR.
Sounds awesome, I would love to see it implemented.
@MmKolodziej did you make any progress on this?
here is my solution on this matter:
require 'websocket-eventmachine-client'
require 'forwardable'
require 'json'
class Websocket
extend Forwardable
ATTR_READER = %i[
_websocket_client _uri _subscribed connection_tries
]
ATTR_WRITER = %i[
_subscribed connection_tries
]
attr_reader *ATTR_READER
attr_writer *ATTR_WRITER
def initialize(uri:, params:, connect_on_start: true, headers: {}, tls: {})
@_uri = uri
@connection_tries = 0
@_subscribed = false
# @_message_factory = MessageFactory.new(params)
@_websocket_client = WebSocket::EventMachine::Client.connect(uri: @_uri, headers: headers, tls: tls)
connect!(headers, tls) if connect_on_start
end
def connect!(headers = {}, tls = {})
_websocket_client.onopen do
self.connection_tries += 1
puts "Connected"
puts "Connection attempt #{connection_tries}"
end
_websocket_client.onclose do |code, reason|
puts "Disconnected with status code: #{code}"
self._subscribed = false
_disconnected_callback&.call
end
_websocket_client.onmessage do |msg, type|
if msg.include?('disconnect')
message = JSON.parse(msg)
if message['reconnect'] == true
puts "reconnecting to server please wait..."
EM.add_timer(3) do
EventMachine.reconnect "app.example.dev", 443, _websocket_client
_websocket_client.post_init
end
else
puts "proceeding to disconnect"
end
else
puts "Received message: #{msg}"
end
end
end
end
# Then we can use it by calling it like this
EventMachine.run do
uri = "wss://app.example.dev/cable"
client = Websocket.new(uri: uri, params: 'ClientUserChannel', headers: {
'Authorization' => "Token token=#{token}" # If needed
})
end