Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4, Live Streaming, stays open, blocking requests

I'm trying to use Rails 4 Live Streaming component. It all works except that it seems like the stream stays open and blocks new request.

How can I ensure that the connection close down properly when closing down or clicking on a new link within the application?

This is my live event controller.

  def events
    response.headers["Content-Type"] = "text/event-stream"
    redis = Redis.new
    redis.psubscribe("participants.*") do |on|
      on.pmessage do |pattern, event, data|
        response.stream.write("event: #{event}\n")
        response.stream.write("data: #{data}\n\n")
      end
    end
  rescue IOError
  ensure
    redis.quit
    response.stream.close
  end

Database conf

production:
  adapter: postgresql
  encoding: unicode
  database: ************
  pool: 1000
  username: ************
  password: ************
  timeout: 5000

I'm using puma as standalone webserver (i don't have heavy static files that need to be served by nginx) on Ubuntu 10.04 with postgresql 9.2.x.

like image 865
Philip Avatar asked Aug 05 '13 09:08

Philip


2 Answers

You have to change the development environment settings to enable this feature.

Add or change this in your config/environments/development.rb:

config.cache_classes = true
config.eager_load = true

See http://railscasts.com/episodes/401-actioncontroller-live?view=asciicast

like image 141
Michael Schäfermeyer Avatar answered Nov 19 '22 12:11

Michael Schäfermeyer


Puma shouldn't be blocking and should allow multiple threads to allow multiple requests.

To walk you through what is happening in your code. You are currently using two threads in this code per request. The thread the request came in on, and a background thread used to hold open the connection.

Your connections will properly close due to the ensure block at the end of your action method.

def events
  response.headers["Content-Type"] = "text/event-stream"
  redis = Redis.new
  # blocks the current thread
  redis.psubscribe("participants.*") do |on|
    on.pmessage do |pattern, event, data|
      response.stream.write("event: #{event}\n")
      response.stream.write("data: #{data}\n\n")
    end
  end
  # stream is on a background thread and will remain open until
  # redis.psubscrie exits. (IO Error, etc)
rescue IOError
ensure
  redis.quit
  response.stream.close
end

You could also investigate another server called rainbows (http://rainbows.rubyforge.org/index.html) which is another very good rack server for open requests.

Here is also a thread related to streaming threads hanging https://github.com/rails/rails/issues/10989

like image 29
Dan Avatar answered Nov 19 '22 10:11

Dan