about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-12-08 00:50:34 -0800
committerEric Wong <normalperson@yhbt.net>2009-12-08 00:51:38 -0800
commit067b54ff7950084fc729df04a748e02361d46dc1 (patch)
tree5e31835fe70fbb8d976960123de83784f7803fa5
parentd2aba3d27fcff72b4db9d3f164247923d1ebd244 (diff)
downloadrainbows-067b54ff7950084fc729df04a748e02361d46dc1.tar.gz
There's a good chunk of tests that fail with this, still.
Worse, I haven't been able to figure out what's wrong since
it looks like it would involve looking at C++ code...
-rw-r--r--lib/rainbows.rb1
-rw-r--r--lib/rainbows/event_machine_defer.rb54
-rw-r--r--lib/rainbows/http_server.rb7
-rw-r--r--t/simple-http_EventMachineDefer.ru11
4 files changed, 72 insertions, 1 deletions
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index eb50f34..4b80056 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -82,6 +82,7 @@ module Rainbows
     :RevThreadSpawn => 50,
     :RevThreadPool => 50,
     :EventMachine => 50,
+    :EventMachineDefer => 50,
     :FiberSpawn => 50,
     :FiberPool => 50,
     :ActorSpawn => 50,
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
diff --git a/lib/rainbows/http_server.rb b/lib/rainbows/http_server.rb
index 8b9f220..c4f804a 100644
--- a/lib/rainbows/http_server.rb
+++ b/lib/rainbows/http_server.rb
@@ -61,7 +61,12 @@ module Rainbows
       end
       mod.setup if mod.respond_to?(:setup)
       Const::RACK_DEFAULTS['rainbows.model'] = @use = model.to_sym
-      Const::RACK_DEFAULTS['rack.multithread'] = !!(/Thread/ =~ model.to_s)
+
+      Const::RACK_DEFAULTS['rack.multithread'] = case model.to_s
+      when /Thread/, "EventMachineDefer"; true
+      else false
+      end
+
       case @use
       when :Rev, :EventMachine, :NeverBlock
         Const::RACK_DEFAULTS['rainbows.autochunk'] = true
diff --git a/t/simple-http_EventMachineDefer.ru b/t/simple-http_EventMachineDefer.ru
new file mode 100644
index 0000000..71269fa
--- /dev/null
+++ b/t/simple-http_EventMachineDefer.ru
@@ -0,0 +1,11 @@
+use Rack::ContentLength
+use Rack::ContentType
+run lambda { |env|
+  if env['rack.multithread'] == true &&
+     EM.reactor_running? &&
+     env['rainbows.model'] == :EventMachineDefer
+    [ 200, {}, [ env.inspect << "\n" ] ]
+  else
+    raise "incorrect parameters"
+  end
+}