rubyeventmachinefaye

looping gets in Eventmachine / faye websocket


This is a serverside websocket client. I'm trying to get user input on a loop, then send that as a websocket message to a server. The basic actions are working and I can ping/pong the server. But it's not working to place a loop in the websocket on(:open) function:

Client (excerpt):

  require 'faye/websocket'
  require 'eventmachine'

   EM.run do
     ws = Faye::WebSocket::Client.new('ws://localhost:3000/')
     ws.on :message do |event|
       puts event.data
     end
     ws.on :open do |event|
       ws.send "predefined"        # this works
       ws.send gets.chomp          # this does too
       loop { ws.send gets.chomp } # this does not
     end
  end

Server (excerpt) which seems to be working fine:

  def self.onmessage(request, ws, msg)
    EM.next_tick { Sockets.each{|s| s.send msg.data } }
  end

I think the issue is the loop blocks the on(:open) function from returning and moving the event machine to the next tick.

I can unblock event machine using TickLoop:

def start_tick_loop
  EM.tick_loop do
    Ws.send gets.chomp
  end.on_stop { EM.stop }
end

EM.run {
  Ws.on :open do |event|
    start_tick_loop
  end
}

but this isn't ideal, because each client is blocked by gets.chomp. I want the user input to not block the on(:message) handler from working.

At the end of the day I suppose I can make a wrapper script which watches a file for changes, and send the gets.chomp output there. But I was hoping there was a simpler way.


Solution

  • It ended up working to put a thread inside the tick loop:

      EM.tick_loop do
        Thread.new {
          inp = gets.chomp
          Ws.send inp
        }
      end.on_stop { EM.stop }