From 16c0391066b38e5f3ea834b59632645890519574 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 29 Nov 2009 16:19:02 -0800 Subject: preliminary NeverBlock support with EventMachine --- TODO | 2 -- lib/rainbows.rb | 1 + lib/rainbows/app_pool.rb | 2 +- lib/rainbows/fiber.rb | 6 +++- lib/rainbows/http_server.rb | 2 +- lib/rainbows/never_block.rb | 69 +++++++++++++++++++++++++++++++++++++++++++++ t/GNUmakefile | 4 +-- t/simple-http_NeverBlock.ru | 11 ++++++++ t/t0300-async_sinatra.sh | 2 +- t/t9000-rack-app-pool.sh | 2 +- 10 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 lib/rainbows/never_block.rb create mode 100644 t/simple-http_NeverBlock.ru diff --git a/TODO b/TODO index abcaed8..483bd6a 100644 --- a/TODO +++ b/TODO @@ -11,8 +11,6 @@ care about. * {Packet,Rev,EventMachine}+Fibers -* Neverblock - * {Packet,Rev}ThreadPool * Rev + callcc - current Rev model with callcc (should work with MBARI) diff --git a/lib/rainbows.rb b/lib/rainbows.rb index f2f7af5..c8f77c0 100644 --- a/lib/rainbows.rb +++ b/lib/rainbows.rb @@ -82,6 +82,7 @@ module Rainbows :FiberSpawn => 50, :FiberPool => 50, :ActorSpawn => 50, + :NeverBlock => 50, }.each do |model, _| u = model.to_s.gsub(/([a-z0-9])([A-Z0-9])/) { "#{$1}_#{$2.downcase!}" } autoload model, "rainbows/#{u.downcase!}" diff --git a/lib/rainbows/app_pool.rb b/lib/rainbows/app_pool.rb index 5c85e0a..036fe9c 100644 --- a/lib/rainbows/app_pool.rb +++ b/lib/rainbows/app_pool.rb @@ -91,7 +91,7 @@ module Rainbows # concurrency models self.re ||= begin case env["rainbows.model"] - when :FiberSpawn, :FiberPool, :Revactor + when :FiberSpawn, :FiberPool, :Revactor, :NeverBlock self.pool = Rainbows::Fiber::Queue.new(pool) end true diff --git a/lib/rainbows/fiber.rb b/lib/rainbows/fiber.rb index c30bd7a..ec0cee3 100644 --- a/lib/rainbows/fiber.rb +++ b/lib/rainbows/fiber.rb @@ -1,5 +1,9 @@ # -*- encoding: binary -*- -require 'fiber' +begin + require 'fiber' +rescue LoadError + defined?(NeverBlock) or raise +end module Rainbows diff --git a/lib/rainbows/http_server.rb b/lib/rainbows/http_server.rb index b528942..8b9f220 100644 --- a/lib/rainbows/http_server.rb +++ b/lib/rainbows/http_server.rb @@ -63,7 +63,7 @@ module Rainbows Const::RACK_DEFAULTS['rainbows.model'] = @use = model.to_sym Const::RACK_DEFAULTS['rack.multithread'] = !!(/Thread/ =~ model.to_s) case @use - when :Rev, :EventMachine + when :Rev, :EventMachine, :NeverBlock Const::RACK_DEFAULTS['rainbows.autochunk'] = true end end diff --git a/lib/rainbows/never_block.rb b/lib/rainbows/never_block.rb new file mode 100644 index 0000000..0933c73 --- /dev/null +++ b/lib/rainbows/never_block.rb @@ -0,0 +1,69 @@ +# -*- encoding: binary -*- + +module Rainbows + + # {NeverBlock}[www.espace.com.eg/neverblock/] library that combines + # the EventMachine library with Ruby Fibers. This includes use of + # Thread-based Fibers under Ruby 1.8. It currently does NOT support + # a streaming "rack.input" but is compatible with everything else + # EventMachine supports. + # + # In your Rainbows! config block, you may specify a Fiber pool size + # to limit your application concurrency (without using Rainbows::AppPool) + # + # Rainbows! do + # use :NeverBlock, :pool_size => 50 + # worker_connections 100 + # end + # + module NeverBlock + + DEFAULTS = { + :pool_size => 20, # same default size used by NB + :backend => :EventMachine, # NeverBlock doesn't support Rev yet + } + + # same pool size NB core itself uses + def self.setup + DEFAULTS.each { |k,v| O[k] ||= v } + Integer === O[:pool_size] && O[:pool_size] > 0 or + raise ArgumentError, "pool_size must a be an Integer > 0" + mod = Rainbows.const_get(O[:backend]) + require "never_block" # require EM first since we need a higher version + G.server.extend(mod) + G.server.extend(Core) + end + + module Client + + def self.setup + const_set(:POOL, ::NB::Pool::FiberPool.new(O[:pool_size])) + Rainbows.const_get(O[:backend]).const_get(:Client).module_eval do + include Rainbows::NeverBlock::Client + alias _app_call app_call + undef_method :app_call + alias app_call nb_app_call + end + end + + def nb_app_call + POOL.spawn do + begin + _app_call + rescue => e + handle_error(e) + end + end + end + end + + module Core + def init_worker_process(worker) + super + Client.setup + logger.info "NeverBlock/#{O[:backend]} pool_size=#{O[:pool_size]}" + end + end + + end +end diff --git a/t/GNUmakefile b/t/GNUmakefile index 52f59df..32893ce 100644 --- a/t/GNUmakefile +++ b/t/GNUmakefile @@ -22,7 +22,7 @@ else endif export RUBYLIB RUBY_VERSION -models = ThreadPool ThreadSpawn Rev EventMachine +models = ThreadPool ThreadSpawn Rev EventMachine NeverBlock rp := ) ONENINE := $(shell case $(RUBY_VERSION) in 1.9.*$(rp) echo true;;esac) ifeq ($(ONENINE),true) @@ -30,7 +30,7 @@ ifeq ($(ONENINE),true) models += FiberSpawn models += FiberPool - # technically this works under 1.8, too, it's just slow + # technically this works under 1.8, but wait until rev 0.3.2 models += RevThreadSpawn endif all_models := $(models) Base diff --git a/t/simple-http_NeverBlock.ru b/t/simple-http_NeverBlock.ru new file mode 100644 index 0000000..31ee561 --- /dev/null +++ b/t/simple-http_NeverBlock.ru @@ -0,0 +1,11 @@ +use Rack::ContentLength +use Rack::ContentType +run lambda { |env| + if env['rack.multithread'] == false && + EM.reactor_running? && + env['rainbows.model'] == :NeverBlock + [ 200, {}, [ Thread.current.inspect << "\n" ] ] + else + raise env.inspect + end +} diff --git a/t/t0300-async_sinatra.sh b/t/t0300-async_sinatra.sh index 3cf729c..a623916 100755 --- a/t/t0300-async_sinatra.sh +++ b/t/t0300-async_sinatra.sh @@ -5,7 +5,7 @@ n=10 CONFIG_RU=async_sinatra.ru case $model in -EventMachine) ;; +NeverBlock|EventMachine) ;; *) t_info "skipping $T since it's not compatible with $model" exit 0 diff --git a/t/t9000-rack-app-pool.sh b/t/t9000-rack-app-pool.sh index 544532b..821b6ec 100755 --- a/t/t9000-rack-app-pool.sh +++ b/t/t9000-rack-app-pool.sh @@ -1,7 +1,7 @@ #!/bin/sh . ./test-lib.sh case $model in -*Thread*|*Fiber*|Revactor) ;; +*Thread*|*Fiber*|Revactor|NeverBlock) ;; *) t_info "skipping $T since it's not compatible with $model" exit 0 -- cgit v1.2.3-24-ge0c7