ruby-on-railseventmachinethinem-websocket

Safely stopping em-websocket in rails on thin


I have a rails app I am running on thin server to utilize the EventMachine run loop. The problem is that I would like to be able to include em-websocket to process information coming in from a ws and stop and start the websocket without stopping the EM run loop. This is how I am starting the websocket.

EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws|
  ws.onopen { }
  ws.onclose { }
  ws.onmessage { |msg| }
end

The problem is in the start/stop code. From em-websocket's docs

#Start WebSocket
def self.start(options, &blk)
  EM.epoll
  EM.run do

    trap("TERM") { stop }
    trap("INT")  { stop }

    EventMachine::start_server(options[:host], options[:port],
      EventMachine::WebSocket::Connection, options) do |c|
      blk.call(c)
    end
  end
end


#Stop WebSocket
def self.stop
  puts "Terminating WebSocket Server"
  EventMachine.stop
end

The problem is that the internal em-websocket code does not track the signature coming from EM:start_server to be able to call EventMachine::stop_server(signature) to shut it down. Is there a way I can override these functions without modifying em-websocket so I can safely start / stop these websockets? I would like if it performed more like the standart Eventmachine server.


Solution

  • Seems to me you don't need to use EM::Websocket.start(). Instead write your own start/stop code, then you can manage the signature yourself.

    # start a ws server and return the signature
    # caller is responsible for +trap+ing to stop it later using said signature.
    def start_ws_server(options, &blk)
      return EventMachine::start_server(options[:host], options[:port],
        EventMachine::WebSocket::Connection, options) do |c|
        blk.call(c)
      end
    end
    
    # stop a previously started ws server
    def stop_ws_server(signature)
      EventMachine::stop_server signature
    end
    

    So now you can start and capture the signature and stop it later using it. No trap code in the start method as at that point the signature is unknown. Since you are capturing the sig outside the method you can trap outside too and use the stored sig there.