about summary refs log tree commit homepage
path: root/lib/rainbows/app_pool.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rainbows/app_pool.rb')
-rw-r--r--lib/rainbows/app_pool.rb182
1 files changed, 89 insertions, 93 deletions
diff --git a/lib/rainbows/app_pool.rb b/lib/rainbows/app_pool.rb
index 7996e2b..b406b32 100644
--- a/lib/rainbows/app_pool.rb
+++ b/lib/rainbows/app_pool.rb
@@ -2,105 +2,101 @@
 
 require 'thread'
 
-module Rainbows
+# Rack middleware to limit application-level concurrency independently
+# of network conncurrency in \Rainbows!   Since the +worker_connections+
+# option in \Rainbows! is only intended to limit the number of
+# simultaneous clients, this middleware may be used to limit the
+# number of concurrent application dispatches independently of
+# concurrent clients.
+#
+# Instead of using M:N concurrency in \Rainbows!, this middleware
+# allows M:N:P concurrency where +P+ is the AppPool +:size+ while
+# +M+ remains the number of +worker_processes+ and +N+ remains the
+# number of +worker_connections+.
+#
+#   rainbows master
+#    \_ rainbows worker[0]
+#    |  \_ client[0,0]------\      ___app[0]
+#    |  \_ client[0,1]-------\    /___app[1]
+#    |  \_ client[0,2]-------->--<       ...
+#    |  ...                __/    `---app[P]
+#    |  \_ client[0,N]----/
+#    \_ rainbows worker[1]
+#    |  \_ client[1,0]------\      ___app[0]
+#    |  \_ client[1,1]-------\    /___app[1]
+#    |  \_ client[1,2]-------->--<       ...
+#    |  ...                __/    `---app[P]
+#    |  \_ client[1,N]----/
+#    \_ rainbows worker[M]
+#       \_ client[M,0]------\      ___app[0]
+#       \_ client[M,1]-------\    /___app[1]
+#       \_ client[M,2]-------->--<       ...
+#       ...                __/    `---app[P]
+#       \_ client[M,N]----/
+#
+# AppPool should be used if you want to enforce a lower value of +P+
+# than +N+.
+#
+# AppPool has no effect on the Rev or EventMachine concurrency models
+# as those are single-threaded/single-instance as far as application
+# concurrency goes.  In other words, +P+ is always +one+ when using
+# Rev or EventMachine.  As of \Rainbows! 0.7.0, it is safe to use with
+# Revactor and the new FiberSpawn and FiberPool concurrency models.
+#
+# Since this is Rack middleware, you may load this in your Rack
+# config.ru file and even use it in threaded servers other than
+# \Rainbows!
+#
+#   use Rainbows::AppPool, :size => 30
+#   map "/lobster" do
+#     run Rack::Lobster.new
+#   end
+#
+# You may to load this earlier or later in your middleware chain
+# depending on the concurrency/copy-friendliness of your middleware(s).
+class Rainbows::AppPool < Struct.new(:pool, :re)
 
-  # Rack middleware to limit application-level concurrency independently
-  # of network conncurrency in \Rainbows!   Since the +worker_connections+
-  # option in \Rainbows! is only intended to limit the number of
-  # simultaneous clients, this middleware may be used to limit the
-  # number of concurrent application dispatches independently of
-  # concurrent clients.
-  #
-  # Instead of using M:N concurrency in \Rainbows!, this middleware
-  # allows M:N:P concurrency where +P+ is the AppPool +:size+ while
-  # +M+ remains the number of +worker_processes+ and +N+ remains the
-  # number of +worker_connections+.
-  #
-  #   rainbows master
-  #    \_ rainbows worker[0]
-  #    |  \_ client[0,0]------\      ___app[0]
-  #    |  \_ client[0,1]-------\    /___app[1]
-  #    |  \_ client[0,2]-------->--<       ...
-  #    |  ...                __/    `---app[P]
-  #    |  \_ client[0,N]----/
-  #    \_ rainbows worker[1]
-  #    |  \_ client[1,0]------\      ___app[0]
-  #    |  \_ client[1,1]-------\    /___app[1]
-  #    |  \_ client[1,2]-------->--<       ...
-  #    |  ...                __/    `---app[P]
-  #    |  \_ client[1,N]----/
-  #    \_ rainbows worker[M]
-  #       \_ client[M,0]------\      ___app[0]
-  #       \_ client[M,1]-------\    /___app[1]
-  #       \_ client[M,2]-------->--<       ...
-  #       ...                __/    `---app[P]
-  #       \_ client[M,N]----/
-  #
-  # AppPool should be used if you want to enforce a lower value of +P+
-  # than +N+.
-  #
-  # AppPool has no effect on the Rev or EventMachine concurrency models
-  # as those are single-threaded/single-instance as far as application
-  # concurrency goes.  In other words, +P+ is always +one+ when using
-  # Rev or EventMachine.  As of \Rainbows! 0.7.0, it is safe to use with
-  # Revactor and the new FiberSpawn and FiberPool concurrency models.
-  #
-  # Since this is Rack middleware, you may load this in your Rack
-  # config.ru file and even use it in threaded servers other than
-  # \Rainbows!
-  #
-  #   use Rainbows::AppPool, :size => 30
-  #   map "/lobster" do
-  #     run Rack::Lobster.new
-  #   end
-  #
-  # You may to load this earlier or later in your middleware chain
-  # depending on the concurrency/copy-friendliness of your middleware(s).
-
-  class AppPool < Struct.new(:pool, :re)
-
-    # +opt+ is a hash, +:size+ is the size of the pool (default: 6)
-    # meaning you can have up to 6 concurrent instances of +app+
-    # within one \Rainbows! worker process.  We support various
-    # methods of the +:copy+ option: +dup+, +clone+, +deep+ and +none+.
-    # Depending on your +app+, one of these options should be set.
-    # The default +:copy+ is +:dup+ as is commonly seen in existing
-    # Rack middleware.
-    def initialize(app, opt = {})
-      self.pool = Queue.new
-      (1...(opt[:size] || 6)).each do
-        pool << case (opt[:copy] || :dup)
-        when :none then app
-        when :dup then app.dup
-        when :clone then app.clone
-        when :deep then Marshal.load(Marshal.dump(app)) # unlikely...
-        else
-          raise ArgumentError, "unsupported copy method: #{opt[:copy].inspect}"
-        end
+  # +opt+ is a hash, +:size+ is the size of the pool (default: 6)
+  # meaning you can have up to 6 concurrent instances of +app+
+  # within one \Rainbows! worker process.  We support various
+  # methods of the +:copy+ option: +dup+, +clone+, +deep+ and +none+.
+  # Depending on your +app+, one of these options should be set.
+  # The default +:copy+ is +:dup+ as is commonly seen in existing
+  # Rack middleware.
+  def initialize(app, opt = {})
+    self.pool = Queue.new
+    (1...(opt[:size] || 6)).each do
+      pool << case (opt[:copy] || :dup)
+      when :none then app
+      when :dup then app.dup
+      when :clone then app.clone
+      when :deep then Marshal.load(Marshal.dump(app)) # unlikely...
+      else
+        raise ArgumentError, "unsupported copy method: #{opt[:copy].inspect}"
       end
-      pool << app # the original
     end
+    pool << app # the original
+  end
 
-    # Rack application endpoint, +env+ is the Rack environment
-    def call(env) # :nodoc:
+  # Rack application endpoint, +env+ is the Rack environment
+  def call(env) # :nodoc:
 
-      # we have to do this check at call time (and not initialize)
-      # because of preload_app=true and models being changeable with SIGHUP
-      # fortunately this is safe for all the reentrant (but not multithreaded)
-      # classes that depend on it and a safe no-op for multithreaded
-      # concurrency models
-      self.re ||= begin
-        case env["rainbows.model"]
-        when :FiberSpawn, :FiberPool, :Revactor, :NeverBlock, :RevFiberSpawn
-          self.pool = Rainbows::Fiber::Queue.new(pool)
-        end
-        true
+    # we have to do this check at call time (and not initialize)
+    # because of preload_app=true and models being changeable with SIGHUP
+    # fortunately this is safe for all the reentrant (but not multithreaded)
+    # classes that depend on it and a safe no-op for multithreaded
+    # concurrency models
+    self.re ||= begin
+      case env["rainbows.model"]
+      when :FiberSpawn, :FiberPool, :Revactor, :NeverBlock, :RevFiberSpawn
+        self.pool = Rainbows::Fiber::Queue.new(pool)
       end
-
-      app = pool.shift
-      app.call(env)
-      ensure
-        pool << app
+      true
     end
+
+    app = pool.shift
+    app.call(env)
+    ensure
+      pool << app
   end
 end