0

I am using websocket on a server as below. It responds to onmessage events, and are conditioned to do different tasks according to the message:

require "websocket-eventmachine-server"

WebSocket::EventMachine::Server.start(host: some_server_name, port: some_port) do |ws|
  # (A) Here, the current thread is the main thread
  ws.onmessage do |s|
    if foo
      # (B) Here, the current thread is the main thread
      ...
    else
      # (C) Here, the current thread is the main thread
      ...
    end 
  end
end

The thread where every onmessage event is executed (described as B and C above) is the same each time, and they are the same as the main thread (described as A above).

I want to execute code in B in a separate thread as C. One way to do that is to put the operations in B and C within a new thread as below:

WebSocket::EventMachine::Server.start(host: some_server_name, port: some_port) do |ws|
  # (A) Here, the current thread is the main thread
  ws.onmessage do |s|
    if foo
      # (B) Here, the current thread will be created each time.
      Thread.new{...}
    else
      # (C) Here, the current thread will be created each time.
      Thread.new{...}
    end
  end
end

but creating a new thread every time an event occurs seems to be heavy, and is making the response slow. So, I want one thread to be shared among all onmessage events processed in B, and another one to be shared among all events processed in C:

WebSocket::EventMachine::Server.start(host: some_server_name, port: some_port) do |ws|
  # (A) Here, the current thread is the main thread
  ws.onmessage do |s|
    if foo
      # (B) I want this part to be executed in a thread
      #     that does not change each time, but is different from the thread in C
      ...
    else
      # (C) I want this part to be executed in a thread
      #     that does not change each time, but is different from the thread in B
      ...
    end
  end
end

What would be a good way to do this? Or, is there a better structure to respond to websocket onmessage events in a mutually non-blocking way?

sawa
  • 165,429
  • 45
  • 277
  • 381

2 Answers2

2

Use EventMachine.defer method to execute code in it's internal thread pool.

synapse
  • 5,588
  • 6
  • 35
  • 65
  • You didn't make it clear enough, but there is `WebSocket::EventMachine.defer` in addition to `EventMachine.defer`. – sawa Nov 24 '13 at 22:24
-2

You can make queue(s) of messages received, and make one thread by queue for execute the traitment :

def do_foo(message)
   .... your code
end
def do_fee(message)
   .... your code
end

queueA= Queue.new
queueB= Queue.new
Thread.new { loop { do_foo(queueA.pop) } }
Thread.new { loop { do_fee(queueB.pop) } }
WebSocket::EventMachine::Server.start(host: some_server_name, port: some_port) do |ws|
  # (A) Here, the current thread is the main thread
  ws.onmessage do |s|
    if foo
       queueA.push(s)
    else
       queueB.push(s)
    end
  end
end

Warning !! if do_foo/fee need to send message on the websocket, you should call the 'if foo..' in a a EM.next_tick { if .. }.

raubarede
  • 423
  • 3
  • 6