about summary refs log tree commit homepage
path: root/lib/rainbows/event_machine_defer.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rainbows/event_machine_defer.rb')
-rw-r--r--lib/rainbows/event_machine_defer.rb54
1 files changed, 54 insertions, 0 deletions
diff --git a/lib/rainbows/event_machine_defer.rb b/lib/rainbows/event_machine_defer.rb
new file mode 100644
index 0000000..4625ab8
--- /dev/null
+++ b/lib/rainbows/event_machine_defer.rb
@@ -0,0 +1,54 @@
+require 'rainbows/event_machine'
+
+module Rainbows
+  module EventMachineDefer
+    include Rainbows::EventMachine
+
+    class Client < Rainbows::EventMachine::Client
+      undef_method :app_call
+
+      def defer_op
+        @env[RACK_INPUT] = @input
+        @env[REMOTE_ADDR] = @remote_addr
+        @env[ASYNC_CALLBACK] = method(:response_write)
+        catch(:async) { APP.call(@env.update(RACK_DEFAULTS)) }
+        rescue => e
+          handle_error(e)
+          nil
+      end
+
+      def defer_callback(response)
+        # too tricky to support pipelining with :async since the
+        # second (pipelined) request could be a stuck behind a
+        # long-running async response
+        (response.nil? || -1 == response.first) and return @state = :close
+
+        resume
+
+        alive = @hp.keepalive? && G.alive
+        out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers?
+        response_write(response, out, alive)
+        if alive
+          @env.clear
+          @hp.reset
+          @state = :headers
+          if @hp.headers(@env, @buf)
+            EM.next_tick(method(:app_call))
+          else
+            set_comm_inactivity_timeout(G.kato)
+          end
+        else
+          quit
+        end
+      end
+
+      def app_call
+        pause
+        set_comm_inactivity_timeout(0)
+        # defer_callback(defer_op)
+        EM.defer(method(:defer_op), method(:defer_callback))
+      end
+    end
+
+  end
+end