From 067b54ff7950084fc729df04a748e02361d46dc1 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 8 Dec 2009 00:50:34 -0800 Subject: EventMachineDefer: preliminary (and) broken version 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... --- lib/rainbows.rb | 1 + lib/rainbows/event_machine_defer.rb | 54 +++++++++++++++++++++++++++++++++++++ lib/rainbows/http_server.rb | 7 ++++- t/simple-http_EventMachineDefer.ru | 11 ++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 lib/rainbows/event_machine_defer.rb create mode 100644 t/simple-http_EventMachineDefer.ru 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 +} -- cgit v1.2.3-24-ge0c7