0

I'm writing rails app and i want user to receive notification as soon as new message is saved to DB. For websocket i'm using em-websocket gem. After connection, i store client id and socket instance in array.

Question: How to push data to the client from controller\model action (before_save for example)? Is it able to do so with em-websocket?

chat.rb

EVENTCHAT_CONFIG = YAML.load_file("#{Rails.root}/config/eventchat.yml")[Rails.env].symbolize_keys

#escape html/xss
include ERB::Util

Thread.abort_on_exception = true

Thread.new {
  EventMachine.run {
    @sockets = Array.new

    EventMachine::WebSocket.start(EVENTCHAT_CONFIG) do |ws|
      ws.onopen do

      end

      ws.onclose do
        index = @sockets.index {|i| i[:socket] == ws}
        client = @sockets.delete_at index
        @sockets.each {|s| s[:socket].send h("#{client[:id]} has disconnected!")}
      end

      ws.onmessage do |msg|
        client = JSON.parse(msg).symbolize_keys
        case client[:action]
        when 'connect'
          @sockets.push({:id=>client[:id], :socket=>ws})
          @sockets.each {|s| s[:socket].send h("#{client[:id]} has connected!")}
        when 'say'
          @sockets.each {|s| s[:socket].send h("#{client[:id]} says : #{client[:data]}")}
        end
      end
    end
  }
}
Src
  • 5,252
  • 5
  • 28
  • 56

1 Answers1

0

When deploying - you may have problems related to having a separate EM reactor in each rails worker (for example errors about some failing to bind to socket or not all users receiving all messages)

Rails controllers in relation to websocket reactor are just another type of client, easiest way is to open a connection with special client id, push some data and close it afterwards. More efficient way - is to keep a open connection from each rails worker

If a EM-based single-process server is used(for example - thin), you can use EM::Queue to deliver messages to websocket worker in-process or even write to websocket directly from controller

Vasfed
  • 18,013
  • 10
  • 47
  • 53