diff options
author | Eric Wong <normalperson@yhbt.net> | 2009-12-30 01:27:15 -0800 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2009-12-30 01:53:46 -0800 |
commit | 96fbc5e91017c4912169629abc7dbb56cda9082c (patch) | |
tree | 763cc51001ef8459e8e65b315740701b15a2b48d /lib/rainbows/event_machine.rb | |
parent | 44a80df0c4c0d47fd2ac503396cb9accfe770f0a (diff) | |
download | rainbows-96fbc5e91017c4912169629abc7dbb56cda9082c.tar.gz |
Some async apps rely on more than just "async.callback" and make full use of Deferrables provided by the EM::Deferrable module. Thanks to James Tucker for bringing this to our attention.
Diffstat (limited to 'lib/rainbows/event_machine.rb')
-rw-r--r-- | lib/rainbows/event_machine.rb | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/lib/rainbows/event_machine.rb b/lib/rainbows/event_machine.rb index bcc0240..aacdfb5 100644 --- a/lib/rainbows/event_machine.rb +++ b/lib/rainbows/event_machine.rb @@ -37,6 +37,7 @@ module Rainbows def initialize(io) @_io = io + @body = nil end alias write send_data @@ -54,6 +55,9 @@ module Rainbows @env[REMOTE_ADDR] = @remote_addr @env[ASYNC_CALLBACK] = method(:response_write) + # we're not sure if anybody uses this, but Thin sets it, too + @env[ASYNC_CLOSE] = EM::DefaultDeferrable.new + response = catch(:async) { APP.call(@env.update(RACK_DEFAULTS)) } # too tricky to support pipelining with :async since the @@ -77,9 +81,14 @@ module Rainbows end while true end - def response_write(response, out = [], alive = false) - body = response.last - unless body.respond_to?(:to_path) + def response_write(response, out = [ CONN_CLOSE ], alive = false) + @body = body = response.last + if body.respond_to?(:errback) && body.respond_to?(:callback) + body.callback { quit } + body.errback { quit } + HttpResponse.write(self, response, out) + return + elsif ! body.respond_to?(:to_path) HttpResponse.write(self, response, out) quit unless alive return @@ -120,6 +129,8 @@ module Rainbows end def unbind + async_close = @env[ASYNC_CLOSE] and async_close.succeed + @body.respond_to?(:fail) and @body.fail @_io.close end end |