Situation
I connect to a WebSocket with Chrome's Remote Debugging Protocol, using a Rails application and a class that implements Celluloid, or more specifically, celluloid-websocket-client
.
The problem is that I don't know how to disconnect the WebSocket cleanly.
When an error happens inside the actor, but the main program runs, Chrome somehow still makes the WebSocket unavailable, not allowing me to attach again.
Code Example
Here's the code, completely self-contained:
require 'celluloid/websocket/client'
class MeasurementConnection
include Celluloid
def initialize(url)
@ws_client = Celluloid::WebSocket::Client.new url, Celluloid::Actor.current
end
# When WebSocket is opened, register callbacks
def on_open
puts "Websocket connection opened"
# @ws_client.close to close it
end
# When raw WebSocket message is received
def on_message(msg)
puts "Received message: #{msg}"
end
# Send a raw WebSocket message
def send_chrome_message(msg)
@ws_client.text JSON.dump msg
end
# When WebSocket is closed
def on_close(code, reason)
puts "WebSocket connection closed: #{code.inspect}, #{reason.inspect}"
end
end
MeasurementConnection.new ARGV[0].strip.gsub("\"","")
while true
sleep
end
What I've tried
When I uncomment
@ws_client.close
, I get:NoMethodError: undefined method `close' for #<Celluloid::CellProxy(Celluloid::WebSocket::Client::Connection:0x3f954f44edf4)
But I thought this was delegated? At least the
.text
method works too?When I call
terminate
instead (to quit the Actor), the WebSocket is still opened in the background.When I call
terminate
on theMeasurementConnection
object that I create in the main code, it makes the Actor appear dead, but still does not free the connection.
How to reproduce
You can test this yourself by starting Chrome with --remote-debugging-port=9222
as command-line argument, then checking curl http://localhost:9222/json
and using the webSocketDebuggerUrl
from there, e.g.:
ruby chrome-test.rb $(curl http://localhost:9222/json 2>/dev/null | grep webSocket | cut -d ":" -f2-)
If no webSocketDebuggerUrl
is available, then something is still connecting to it.
It used to work when I was using EventMachine
similar to this example, but not with faye/websocket-client
, but em-websocket-client
instead. Here, upon stopping the EM loop (with EM.stop
), the WebSocket would become available again.
I figured it out. I used the 0.0.1 version of the
celluloid-websocket-client
gem which did not delegate theclose
method.Using 0.0.2 worked, and the code would look like this:
In
MeasurementConnection
:In the main code: