diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2012-07-29 17:26:07 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2012-07-29 21:43:05 -0700 |
commit | af0a9f9eefaee3a8120cfd8d05cbc431af376da3 (patch) | |
tree | 3eca858f42bf55c2e1d660434f3e782c524debab /actionpack | |
parent | d4433a35215c5e32d5cb91885c4084f849988887 (diff) | |
download | rails-af0a9f9eefaee3a8120cfd8d05cbc431af376da3.tar.gz rails-af0a9f9eefaee3a8120cfd8d05cbc431af376da3.tar.bz2 rails-af0a9f9eefaee3a8120cfd8d05cbc431af376da3.zip |
added live responses which can be written and read in separate threads
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/lib/action_controller.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/live.rb | 42 | ||||
-rw-r--r-- | actionpack/test/controller/live_stream_test.rb | 26 | ||||
-rw-r--r-- | actionpack/test/dispatch/live_response_test.rb | 34 |
4 files changed, 103 insertions, 0 deletions
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 7c10fcbb8a..1d06c83338 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -1,5 +1,6 @@ require 'abstract_controller' require 'action_dispatch' +require 'action_controller/metal/live' module ActionController extend ActiveSupport::Autoload diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb new file mode 100644 index 0000000000..aea00849d3 --- /dev/null +++ b/actionpack/lib/action_controller/metal/live.rb @@ -0,0 +1,42 @@ +require 'action_dispatch/http/response' + +module ActionController + module Live + class Response < ActionDispatch::Response + class Buffer < ActionDispatch::Response::Buffer # :nodoc: + def initialize(response) + @response = response + @buf = Queue.new + end + + def write(string) + unless @response.committed? + @response.headers["Cache-Control"] = "no-cache" + @response.headers.delete("Content-Length") + end + + super + end + + def each + while str = @buf.pop + yield str + end + end + + def close + super + @buf.push nil + end + end + + private + + def build_buffer(response, body) + buf = Buffer.new response + body.each { |part| buf.write part } + buf + end + end + end +end diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb new file mode 100644 index 0000000000..6ee6444065 --- /dev/null +++ b/actionpack/test/controller/live_stream_test.rb @@ -0,0 +1,26 @@ +require 'abstract_unit' + +module ActionController + class StreamingResponseTest < ActionController::TestCase + class TestController < ActionController::Base + def self.controller_path + 'test' + end + + def basic_stream + %w{ hello world }.each do |word| + response.stream.write word + response.stream.write "\n" + end + response.stream.close + end + end + + tests TestController + + def test_write_to_stream + get :basic_stream + assert_equal "hello\nworld\n", @response.body + end + end +end diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb new file mode 100644 index 0000000000..0e8dcc6a16 --- /dev/null +++ b/actionpack/test/dispatch/live_response_test.rb @@ -0,0 +1,34 @@ +require 'abstract_unit' +require 'active_support/concurrency/latch' + +module ActionController + module Live + class ResponseTest < ActiveSupport::TestCase + def setup + @response = Live::Response.new + end + + def test_parallel + latch = ActiveSupport::Concurrency::Latch.new + + t = Thread.new { + @response.stream.write 'foo' + latch.await + @response.stream.close + } + + @response.each do |part| + assert_equal 'foo', part + latch.release + end + assert t.join + end + + def test_setting_body_populates_buffer + @response.body = 'omg' + @response.close + assert_equal ['omg'], @response.body_parts + end + end + end +end |