At the time if this question, the syntax was right. But now it's not, as of 0.17.0
of Celluloid
... but that's not the answer, that's just a preface. I've forked and edited your gist:
https://gist.github.com/digitalextremist/7dc74b03587cd4b3b7dd
Here is the new gist:
require 'celluloid/current'
require 'celluloid/io'
require 'json'
class TestServer
include Celluloid::IO
finalizer :shutdown
def initialize(host, port)
puts "*** Starting echo server on #{host}:#{port}"
# Since we included Celluloid::IO, we're actually making a
# Celluloid::IO::TCPServer here
@server = TCPServer.new(host, port)
end
def shutdown
@server.close rescue nil
end
def run
loop {
async.handle_connection(@server.accept)
}
end
def handle_connection(socket)
addr = *socket.peeraddr
puts "*** Received connection from #{addr[3]}:#{addr[1]}"
# This is just a test, followed this format:
# https://github.com/soldair/pinoccio-server/blob/master/troop.js#L163
cmd = {
:type => "command",
:to => 1,
:timeout => 10000,
:command => "led.on"
}
json_cmd = "#{cmd.to_json}\n"
socket.write json_cmd # The light never turns on. Why?
puts json_cmd
loop {
puts socket.readpartial(4096)
}
rescue EOFError
puts "*** #{addr[3]}:#{addr[1]} disconnected"
rescue => ex
echo "Trouble with socket: [#{ex.class}] #{ex.message}"
ensure
socket.close rescue nil
end
end
TestServer.supervise(as: :test_server, args: ["0.0.0.0", 1234])
#de Not needed. Killed by Celluloid.shutdown already...
#de trap("INT") { supervisor.terminate; exit }
#de Avoid starting the server in the constructor, then sleeping.
#de Could end up with a race condition, and/or botch instantiation.
#de But with that being said, you need to detect crashes... so:
loop {
begin
Celluloid[:test_server].run
rescue => ex
echo "Trouble with supervised server: [#{ex.class}] #{ex.message}"
echo "Waiting 1.26 seconds for actor to be reinstantiated."
sleep 1.26
end
}
Notable changes:
- Invoke
Celluloid
first, and let it spin up properly.
- No longer start the server in
initialize
.
- Catch the death of the server, and restart it after the actor is reinstantiated.
- Become compliant with the new API.
- Forcefully, silently close server at end.
- Forcefully, silently close socket at disconnect.
- Avoid duplicating shutdown already started by
Celluloid
itself.
- Avoid using the hostname, which is often not there. Show numeric address.
- Catch the type of error that'd be caused by a write, and show you the reason.
- Closure of the socket will always happen, regardless of how the socket dies.
The code you originally started from should have worked, or at least it ought to have given you a clear reason why it wasn't working. The above code is now compatible with Celluloid
as of 0.17.0
and same for the new Celluloid::IO
... if you have any further problems, please include the specific error.
Note: You will need to possibly detect that the server crashed and is still holding open the port you expect to be available, and that is not included in the example... but an example of that is given in the Celluloid::IO
test suite: