common Rainbows.accept method
[rainbows.git] / lib / rainbows.rb
bloba252ba637ff715150891abfa252c974a3efab0e4
1 # -*- encoding: binary -*-
2 require 'unicorn'
3 require 'rainbows/error'
5 module Rainbows
7   # global vars because class/instance variables are confusing me :<
8   # this struct is only accessed inside workers and thus private to each
9   # G.cur may not be used in the network concurrency model
10   class State < Struct.new(:alive,:m,:cur,:kato,:server,:tmp)
11     def tick
12       tmp.chmod(self.m = m == 0 ? 1 : 0)
13       alive && server.master_pid == Process.ppid or quit!
14     end
16     def quit!
17       self.alive = false
18       server.class.const_get(:LISTENERS).map! { |s| s.close rescue nil }
19       false
20     end
21   end
22   G = State.new(true, 0, 0, 2)
24   require 'rainbows/const'
25   require 'rainbows/http_server'
26   require 'rainbows/http_response'
27   require 'rainbows/base'
28   autoload :AppPool, 'rainbows/app_pool'
29   autoload :DevFdResponse, 'rainbows/dev_fd_response'
31   class << self
33     # runs the Rainbows! HttpServer with +app+ and +options+ and does
34     # not return until the server has exited.
35     def run(app, options = {})
36       HttpServer.new(app, options).start.join
37     end
38   end
40   # configures \Rainbows! with a given concurrency model to +use+ and
41   # a +worker_connections+ upper-bound.  This method may be called
42   # inside a Unicorn/Rainbows configuration file:
43   #
44   #   Rainbows! do
45   #     use :Revactor # this may also be :ThreadSpawn or :ThreadPool
46   #     worker_connections 400
47   #     keepalive_timeout 0 # zero disables keepalives entirely
48   #   end
49   #
50   #   # the rest of the Unicorn configuration
51   #   worker_processes 8
52   #
53   # See the documentation for the respective Revactor, ThreadSpawn,
54   # and ThreadPool classes for descriptions and recommendations for
55   # each of them.  The total number of clients we're able to serve is
56   # +worker_processes+ * +worker_connections+, so in the above example
57   # we can serve 8 * 400 = 3200 clients concurrently.
58   #
59   # The default is +keepalive_timeout+ is 2 seconds, which should be
60   # enough under most conditions for browsers to render the page and
61   # start retrieving extra elements for.  Increasing this beyond 5
62   # seconds is not recommended.  Zero disables keepalive entirely
63   # (but pipelining fully-formed requests is still works).
64   def Rainbows!(&block)
65     block_given? or raise ArgumentError, "Rainbows! requires a block"
66     HttpServer.setup(block)
67   end
69   # maps models to default worker counts, default worker count numbers are
70   # pretty arbitrary and tuning them to your application and hardware is
71   # highly recommended
72   MODEL_WORKER_CONNECTIONS = {
73     :Base => 1, # this one can't change
74     :Revactor => 50,
75     :ThreadSpawn => 30,
76     :ThreadPool => 10,
77     :Rev => 50,
78     :RevThreadSpawn => 50,
79     :EventMachine => 50,
80     :FiberSpawn => 50,
81     :FiberPool => 50,
82     :ActorSpawn => 50,
83   }.each do |model, _|
84     u = model.to_s.gsub(/([a-z0-9])([A-Z0-9])/) { "#{$1}_#{$2.downcase!}" }
85     autoload model, "rainbows/#{u.downcase!}"
86   end
87   autoload :Fiber, 'rainbows/fiber' # core class
89   # returns nil if accept fails
90   def self.accept(sock)
91     sock.accept_nonblock
92   rescue Errno::EAGAIN, Errno::ECONNABORTED
93   end
95 end
97 # inject the Rainbows! method into Unicorn::Configurator
98 Unicorn::Configurator.class_eval { include Rainbows }