Philip
Philip

Reputation: 7166

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.

Upvotes: 7

Views: 3238

Answers (2)

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

Upvotes: 8

Dan
Dan

Reputation: 1412

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

Upvotes: 2

Related Questions