preliminary NeverBlock support with EventMachine
[rainbows.git] / lib / rainbows / http_server.rb
blob8b9f220033919f5943034298df6c476b2cbd1bc8
1 # -*- encoding: binary -*-
2 require 'rainbows'
3 module Rainbows
5   class HttpServer < ::Unicorn::HttpServer
6     include Rainbows
8     class << self
9       def setup(block)
10         G.server.instance_eval(&block)
11       end
12     end
14     def initialize(app, options)
15       G.server = self
16       rv = super(app, options)
17       defined?(@use) or use(:Base)
18       @worker_connections ||= MODEL_WORKER_CONNECTIONS[@use]
19     end
21     def reopen_worker_logs(worker_nr)
22       logger.info "worker=#{worker_nr} reopening logs..."
23       Unicorn::Util.reopen_logs
24       logger.info "worker=#{worker_nr} done reopening logs"
25       rescue
26         G.quit! # let the master reopen and refork us
27     end
29     #:stopdoc:
30     #
31     # Add one second to the timeout since our fchmod heartbeat is less
32     # precise (and must be more conservative) than Unicorn does.  We
33     # handle many clients per process and can't chmod on every
34     # connection we accept without wasting cycles.  That added to the
35     # fact that we let clients keep idle connections open for long
36     # periods of time means we have to chmod at a fixed interval.
37     alias_method :set_timeout, :timeout=
38     undef_method :timeout=
39     def timeout=(nr)
40       set_timeout(nr + 1)
41     end
42     #:startdoc:
44     def use(*args)
45       model = args.shift or return @use
46       mod = begin
47         Rainbows.const_get(model)
48       rescue NameError
49         raise ArgumentError, "concurrency model #{model.inspect} not supported"
50       end
52       Module === mod or
53         raise ArgumentError, "concurrency model #{model.inspect} not supported"
54       extend(mod)
55       args.each do |opt|
56         case opt
57         when Hash; O.update(opt)
58         when Symbol; O[opt] = true
59         else; raise ArgumentError, "can't handle option: #{opt.inspect}"
60         end
61       end
62       mod.setup if mod.respond_to?(:setup)
63       Const::RACK_DEFAULTS['rainbows.model'] = @use = model.to_sym
64       Const::RACK_DEFAULTS['rack.multithread'] = !!(/Thread/ =~ model.to_s)
65       case @use
66       when :Rev, :EventMachine, :NeverBlock
67         Const::RACK_DEFAULTS['rainbows.autochunk'] = true
68       end
69     end
71     def worker_connections(*args)
72       return @worker_connections if args.empty?
73       nr = args.first
74       (Integer === nr && nr > 0) or
75         raise ArgumentError, "worker_connections must be a positive Integer"
76       @worker_connections = nr
77     end
79     def keepalive_timeout(nr)
80       (Integer === nr && nr >= 0) or
81         raise ArgumentError, "keepalive must be a non-negative Integer"
82       G.kato = nr
83     end
84   end
86 end