J
J
justed_ss2015-10-27 13:16:24
Ruby on Rails
justed_ss, 2015-10-27 13:16:24

How to properly implement SSE in RAILS?

It is necessary that several clients listen to the method that sends, in case of changing / creating a record, this very record in the form of JSON.
Rails 4. database - postgresql, Puma server
The Internet is full of useless instructions where the method sends something at intervals and then closes the connection. Or they write a middleware / module in the lib that, bypassing the routes / controllers / authorization, performs useful functionality, but it all looks like a crutch.
I found something similar to what I need, but there, too, not everything is so smooth
Controller

def index
  response.headers['Content-Type'] = 'text/event-stream'
  sse = SSE.new(response.stream)
  begin
    Comment.on_change do |data|
      sse.write(data)
    end
  rescue IOError
    # Client Disconnected
  ensure
    sse.close
  end
  render nothing: true
end

on_change method. DB event is triggered in standard Rails callbacks
def on_change
    Comment.connection.execute "LISTEN comments"
    loop do
      Comment.connection.raw_connection.wait_for_notify do |event, pid, comment|
        yield comment
      end
    end
ensure
  Comment.connection.execute "UNLISTEN comments"
end

But the server after several connections hangs somewhere at the stage of waiting for an event from the database. I tried more workers, the result did not change much. Well, apparently, every time he keeps a separate connection to the database in anticipation of an event, which causes ActiveRecord to timeout from time to time.
In general, the question is, where to read / look at the "useful" implementation of sse?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexey, 2015-10-29
@fuCtor

There is a nuance with SSE, if you use a non-event application server (unicorn, puma, etc.), then each request will block one of the threads / processes. Over time, they will end and the execution of everything will be waiting for the database or something else blocking.
It's best to use Thin, it's built on EventMachine and doesn't block external request, but can be blocked by DB request.
I made this bundle myself:
Sinatra + Sinatra-SSE is mounted in Rails to accept connections. Event listening (PG, Redis, etc) is done on EM compatible clients. And some connection manager is started that will send out data.
Something like this.

K
khataev, 2019-10-15
@khataev

There is such an option

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question