title: How to get ActionController::Live streaming working with Thin?
body: <h2>Question</h2>
  
  <p>Can you use <code>thin</code> with <code>ActionController::Live</code> to implement Server Side Events (SSE) and long polling?  If so, how?</p>
  
  <h2>Context</h2>
  
  <p>Although the title is a repeat of <a href="https://stackoverflow.com/questions/15441302/how-to-get-rails-4-actioncontrollerlive-streaming-working-with-thin-and-ruby-2">How to get Rails 4 ActionController::Live streaming working with Thin and Ruby 2? And how do Thin and Puma scale with live streaming?</a>, the OP muddied the waters by asking two questions, and this question never got answered.</p>
  
  <p>A number of other posts suggest you CAN use <code>thin</code> for Server Side Events (sse) if you start it via <code>exec thin start --threaded</code>: <a href="https://stackoverflow.com/questions/17897944/does-heroku-support-actioncontrollerlive">Does Heroku support ActionController::Live?</a> and <a href="https://stackoverflow.com/questions/17902386/is-puma-the-only-multi-threaded-rails-4-http-server">Is puma the ONLY multi-threaded rails 4 http server?</a>, Aaron's seminal <a href="http://tenderlovemaking.com/2012/07/30/is-it-live.html" rel="nofollow noreferrer">http://tenderlovemaking.com/2012/07/30/is-it-live.html</a> and Ryan's perennially dependable <a href="http://railscasts.com/episodes/401-actioncontroller-live?view=asciicast" rel="nofollow noreferrer">http://railscasts.com/episodes/401-actioncontroller-live?view=asciicast</a>.  But even though I'm copying the Railscast example, I haven't been able to get it to work with <code>thin</code>.</p>
  
  <h2>What I've tried</h2>
  
  <pre><code># ----------------------------------------------------------------
  # file: config/routes.rb
  Rails.application.routes.draw do
  
    resources :widgets do
      collection do
        get 'events'              # SSE test
      end
    end
  end
  </code></pre>
  
  <p>_</p>
  
  <pre><code># ----------------------------------------------------------------
  # file: config/environments/development.rb
  Rails.application.configure do
      ... snip ...
      # see http://tenderlovemaking.com/2012/07/30/is-it-live.html
      config.preload_frameworks = true
      config.allow_concurrency = true
  end
  </code></pre>
  
  <p>_</p>
  
  <pre><code># ----------------------------------------------------------------
  # file: app/controllers/widgets_controller.rb
  class WidgetsController &lt; ApplicationController
    include ActionController::Live
  
    # GET /widgets/events
    # see http://railscasts.com/episodes/401-actioncontroller-live?view=asciicast
    def events
      # SSE expects the `text/event-stream` content type
      response.headers['Content-Type'] = 'text/event-stream'
      3.times do |n|
        response.stream.write "#{n}...\n\n"
        sleep 2
      end
    ensure
      response.stream.close
    end
  
  end
  </code></pre>
  
  <p>_</p>
  
  <pre><code># ----------------------------------------------------------------
  # Gemfile
  source 'https://rubygems.org'
  
  gem 'rails', '4.1.8'
  gem 'pg'
  ... snip ...
  gem 'thin'
  </code></pre>
  
  <h2>Running it</h2>
  
  <p>In shell window A:</p>
  
  <pre><code>$ bundle install
  Chalcedony[~/Projects/heroku-sample/widget-worker]$ thin start --threaded --trace
  Using rack adapter
  Thin web server (v1.6.3 codename Protein Powder)
  Tracing ON
  Maximum connections set to 1024
  Listening on 0.0.0.0:3000, CTRL+C to stop
  </code></pre>
  
  <p>Then in shell window B:</p>
  
  <pre><code>$ curl --no-buffer localhost:3000/widgets/events
  </code></pre>
  
  <p>Back in shell window A I see the request and the responses being spit out at one second intervals (there's a one second delay between the <code>0...</code> and <code>1...</code> and <code>2...</code>).  That's good:</p>
  
  <pre><code>GET /widgets/events HTTP/1.1
  User-Agent: curl/7.37.1
  Host: localhost:3000
  Accept: */*
  
  
  HTTP/1.1 200 OK
  X-Frame-Options: SAMEORIGIN
  X-XSS-Protection: 1; mode=block
  X-Content-Type-Options: nosniff
  Cache-Control: no-cache
  Content-Type: text/html; charset=utf-8
  X-Request-Id: 95e64eb6-ee21-4e97-a33a-dbf579b3027c
  X-Runtime: 0.066925
  Connection: close
  Server: thin
  
  
  0... &lt;delay...&gt;
  
  
  1... &lt;delay...&gt;
  
  
  2... &lt;delay...&gt;
  </code></pre>
  
  <p>But in shell window B, the printout is delayed and appears all at once.  The same thing happens when I view the page in Chrome.  Have I failed to configure some settings properly?</p>
  
  <h2>P.S.:</h2>
  
  <pre><code>$ rake about
  About your application's environment
  Ruby version              2.1.4-p265 (x86_64-darwin14.0)
  RubyGems version          2.2.2
  Rack version              1.5
  Rails version             4.1.8
  JavaScript Runtime        JavaScriptCore
  Active Record version     4.1.8
  Action Pack version       4.1.8
  Action View version       4.1.8
  Action Mailer version     4.1.8
  Active Support version    4.1.8
  Middleware                Rack::Sendfile, ActionDispatch::Static, #&lt;ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fb0cb4ae1a0&gt;, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::RemoteIp, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::Migration::CheckPending, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, Rack::Head, Rack::ConditionalGet, Rack::ETag
  Environment               development
  Database adapter          postgresql
  Database schema version   20141213003938
  </code></pre>
  
  <h2>P.P.S.</h2>
  
  <p>Right now you might be thinking "<em>Why aren't you using <code>puma</code> like everyone else?</em>"  Good question.  Right now, I'm unable to build the puma gem on my machine for reasons I haven't figured out.  And I've been using <code>thin</code> in most of my heroku deployed apps, so I'm comfortable with it.  If I can't get thin to work, I'll put more effort into building puma.</p>