rubymultithreadingwebsocketeventmachineem-websocket

Run websocket onmessage in different thread


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?


Solution

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