about summary refs log tree commit homepage
path: root/lib/rainbows/event_machine.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-12-30 01:27:15 -0800
committerEric Wong <normalperson@yhbt.net>2009-12-30 01:53:46 -0800
commit96fbc5e91017c4912169629abc7dbb56cda9082c (patch)
tree763cc51001ef8459e8e65b315740701b15a2b48d /lib/rainbows/event_machine.rb
parent44a80df0c4c0d47fd2ac503396cb9accfe770f0a (diff)
downloadrainbows-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.rb17
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