enable the keepalive_requests config option
[rainbows.git] / lib / rainbows / http_server.rb
blob906fa0a3b8586ff892cdff8ec51e42a88a6f7dbe
1 # -*- encoding: binary -*-
2 # :enddoc:
4 class Rainbows::HttpServer < Unicorn::HttpServer
5   G = Rainbows::G
7   def self.setup(block)
8     G.server.instance_eval(&block)
9   end
11   def initialize(app, options)
12     G.server = self
13     @logger = Unicorn::Configurator::DEFAULTS[:logger]
14     rv = super(app, options)
15     defined?(@use) or use(:Base)
16     @worker_connections ||= Rainbows::MODEL_WORKER_CONNECTIONS[@use]
17   end
19   def reopen_worker_logs(worker_nr)
20     logger.info "worker=#{worker_nr} reopening logs..."
21     Unicorn::Util.reopen_logs
22     logger.info "worker=#{worker_nr} done reopening logs"
23     rescue
24       G.quit! # let the master reopen and refork us
25   end
27   # Add one second to the timeout since our fchmod heartbeat is less
28   # precise (and must be more conservative) than Unicorn does.  We
29   # handle many clients per process and can't chmod on every
30   # connection we accept without wasting cycles.  That added to the
31   # fact that we let clients keep idle connections open for long
32   # periods of time means we have to chmod at a fixed interval.
33   def timeout=(nr)
34     @timeout = nr + 1
35   end
37   def load_config!
38     use :Base
39     G.kato = 5
40     Rainbows.max_bytes = 1024 * 1024
41     @worker_connections = nil
42     super
43     @worker_connections ||= Rainbows::MODEL_WORKER_CONNECTIONS[@use]
44   end
46   def ready_pipe=(v)
47     # hacky hook got force Rainbows! to load modules only in workers
48     if @master_pid && @master_pid == Process.ppid
49       extend(Rainbows.const_get(@use))
50     end
51     super
52   end
54   def use(*args)
55     model = args.shift or return @use
56     mod = begin
57       Rainbows.const_get(model)
58     rescue NameError => e
59       logger.error "error loading #{model.inspect}: #{e}"
60       e.backtrace.each { |l| logger.error l }
61       raise ArgumentError, "concurrency model #{model.inspect} not supported"
62     end
64     Module === mod or
65       raise ArgumentError, "concurrency model #{model.inspect} not supported"
66     args.each do |opt|
67       case opt
68       when Hash; O.update(opt)
69       when Symbol; O[opt] = true
70       else; raise ArgumentError, "can't handle option: #{opt.inspect}"
71       end
72     end
73     mod.setup if mod.respond_to?(:setup)
74     new_defaults = {
75       'rainbows.model' => (@use = model.to_sym),
76       'rack.multithread' => !!(model.to_s =~ /Thread/),
77       'rainbows.autochunk' => [:Coolio,:Rev,
78                                :EventMachine,:NeverBlock].include?(@use),
79     }
80     Rainbows::Const::RACK_DEFAULTS.update(new_defaults)
81   end
83   def worker_connections(*args)
84     return @worker_connections if args.empty?
85     nr = args[0]
86     (Integer === nr && nr > 0) or
87       raise ArgumentError, "worker_connections must be a positive Integer"
88     @worker_connections = nr
89   end
91   def keepalive_timeout(nr)
92     (Integer === nr && nr >= 0) or
93       raise ArgumentError, "keepalive_timeout must be a non-negative Integer"
94     G.kato = nr
95   end
97   def keepalive_requests(nr)
98     Integer === nr or
99       raise ArgumentError, "keepalive_requests must be a non-negative Integer"
100     Unicorn::HttpRequest.keepalive_requests = nr
101   end
103   def client_max_body_size(nr)
104     err = "client_max_body_size must be nil or a non-negative Integer"
105     case nr
106     when nil
107     when Integer
108       nr >= 0 or raise ArgumentError, err
109     else
110       raise ArgumentError, err
111     end
112     Rainbows.max_bytes = nr
113   end