puma 3.7.1 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/History.md +229 -1
- data/README.md +179 -212
- data/docs/architecture.md +37 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +24 -4
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/plugins.md +28 -0
- data/docs/restart.md +41 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +130 -37
- data/ext/puma_http11/PumaHttp11Service.java +2 -0
- data/ext/puma_http11/extconf.rb +8 -0
- data/ext/puma_http11/http11_parser.c +84 -84
- data/ext/puma_http11/http11_parser.rl +9 -9
- data/ext/puma_http11/mini_ssl.c +105 -9
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +13 -16
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +30 -6
- data/lib/puma.rb +10 -0
- data/lib/puma/accept_nonblock.rb +2 -0
- data/lib/puma/app/status.rb +13 -0
- data/lib/puma/binder.rb +33 -18
- data/lib/puma/cli.rb +48 -33
- data/lib/puma/client.rb +94 -22
- data/lib/puma/cluster.rb +69 -21
- data/lib/puma/commonlogger.rb +2 -0
- data/lib/puma/configuration.rb +134 -136
- data/lib/puma/const.rb +16 -2
- data/lib/puma/control_cli.rb +31 -18
- data/lib/puma/convenient.rb +5 -3
- data/lib/puma/daemon_ext.rb +2 -0
- data/lib/puma/delegation.rb +2 -0
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +349 -113
- data/lib/puma/events.rb +8 -4
- data/lib/puma/io_buffer.rb +3 -6
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher.rb +60 -36
- data/lib/puma/minissl.rb +85 -28
- data/lib/puma/null_io.rb +2 -0
- data/lib/puma/plugin.rb +2 -0
- data/lib/puma/plugin/tmp_restart.rb +3 -2
- data/lib/puma/rack/builder.rb +4 -1
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +218 -30
- data/lib/puma/runner.rb +18 -4
- data/lib/puma/server.rb +149 -56
- data/lib/puma/single.rb +16 -5
- data/lib/puma/state_file.rb +2 -0
- data/lib/puma/tcp_logger.rb +2 -0
- data/lib/puma/thread_pool.rb +59 -6
- data/lib/puma/util.rb +2 -6
- data/lib/rack/handler/puma.rb +58 -19
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +2 -0
- data/tools/jungle/init.d/puma +8 -8
- data/tools/jungle/init.d/run-puma +1 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/trickletest.rb +1 -1
- metadata +25 -85
- data/.github/issue_template.md +0 -20
- data/Gemfile +0 -12
- data/Manifest.txt +0 -77
- data/Rakefile +0 -158
- data/gemfiles/2.1-Gemfile +0 -12
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
- data/puma.gemspec +0 -52
data/lib/puma/cluster.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puma/runner'
|
2
4
|
require 'puma/util'
|
3
5
|
require 'puma/plugin'
|
@@ -5,9 +7,18 @@ require 'puma/plugin'
|
|
5
7
|
require 'time'
|
6
8
|
|
7
9
|
module Puma
|
10
|
+
# This class is instantiated by the `Puma::Launcher` and used
|
11
|
+
# to boot and serve a Ruby application when puma "workers" are needed
|
12
|
+
# i.e. when using multi-processes. For example `$ puma -w 5`
|
13
|
+
#
|
14
|
+
# At the core of this class is running an instance of `Puma::Server` which
|
15
|
+
# gets created via the `start_server` method from the `Puma::Runner` class
|
16
|
+
# that this inherits from.
|
17
|
+
#
|
18
|
+
# An instance of this class will spawn the number of processes passed in
|
19
|
+
# via the `spawn_workers` method call. Each worker will have it's own
|
20
|
+
# instance of a `Puma::Server`.
|
8
21
|
class Cluster < Runner
|
9
|
-
WORKER_CHECK_INTERVAL = 5
|
10
|
-
|
11
22
|
def initialize(cli, events)
|
12
23
|
super cli, events
|
13
24
|
|
@@ -24,7 +35,35 @@ module Puma
|
|
24
35
|
@workers.each { |x| x.term }
|
25
36
|
|
26
37
|
begin
|
27
|
-
|
38
|
+
if RUBY_VERSION < '2.6'
|
39
|
+
@workers.each do |w|
|
40
|
+
begin
|
41
|
+
Process.waitpid(w.pid)
|
42
|
+
rescue Errno::ECHILD
|
43
|
+
# child is already terminated
|
44
|
+
end
|
45
|
+
end
|
46
|
+
else
|
47
|
+
# below code is for a bug in Ruby 2.6+, above waitpid call hangs
|
48
|
+
t_st = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
49
|
+
pids = @workers.map(&:pid)
|
50
|
+
loop do
|
51
|
+
pids.reject! do |w_pid|
|
52
|
+
begin
|
53
|
+
if Process.waitpid(w_pid, Process::WNOHANG)
|
54
|
+
log " worker status: #{$?}"
|
55
|
+
true
|
56
|
+
end
|
57
|
+
rescue Errno::ECHILD
|
58
|
+
true # child is already terminated
|
59
|
+
end
|
60
|
+
end
|
61
|
+
break if pids.empty?
|
62
|
+
sleep 0.5
|
63
|
+
end
|
64
|
+
t_end = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
65
|
+
log format(" worker shutdown time: %6.2f", t_end - t_st)
|
66
|
+
end
|
28
67
|
rescue Interrupt
|
29
68
|
log "! Cancelled waiting for workers"
|
30
69
|
end
|
@@ -56,12 +95,13 @@ module Puma
|
|
56
95
|
@signal = "TERM"
|
57
96
|
@options = options
|
58
97
|
@first_term_sent = nil
|
98
|
+
@started_at = Time.now
|
59
99
|
@last_checkin = Time.now
|
60
100
|
@last_status = '{}'
|
61
101
|
@dead = false
|
62
102
|
end
|
63
103
|
|
64
|
-
attr_reader :index, :pid, :phase, :signal, :last_checkin, :last_status
|
104
|
+
attr_reader :index, :pid, :phase, :signal, :last_checkin, :last_status, :started_at
|
65
105
|
|
66
106
|
def booted?
|
67
107
|
@stage == :booted
|
@@ -170,7 +210,7 @@ module Puma
|
|
170
210
|
def check_workers(force=false)
|
171
211
|
return if !force && @next_check && @next_check >= Time.now
|
172
212
|
|
173
|
-
@next_check = Time.now + WORKER_CHECK_INTERVAL
|
213
|
+
@next_check = Time.now + Const::WORKER_CHECK_INTERVAL
|
174
214
|
|
175
215
|
any = false
|
176
216
|
|
@@ -187,14 +227,11 @@ module Puma
|
|
187
227
|
# during this loop by giving the kernel time to kill them.
|
188
228
|
sleep 1 if any
|
189
229
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
@workers.delete_if { |w| w.pid == pid }
|
230
|
+
pids = []
|
231
|
+
while pid = Process.waitpid(-1, Process::WNOHANG) do
|
232
|
+
pids << pid
|
195
233
|
end
|
196
|
-
|
197
|
-
@workers.delete_if(&:dead?)
|
234
|
+
@workers.reject! { |w| w.dead? || pids.include?(w.pid) }
|
198
235
|
|
199
236
|
cull_workers
|
200
237
|
spawn_workers
|
@@ -224,12 +261,13 @@ module Puma
|
|
224
261
|
begin
|
225
262
|
@wakeup.write "!" unless @wakeup.closed?
|
226
263
|
rescue SystemCallError, IOError
|
264
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
227
265
|
end
|
228
266
|
end
|
229
267
|
|
230
268
|
def worker(index, master)
|
231
|
-
title
|
232
|
-
title
|
269
|
+
title = "puma: cluster worker #{index}: #{master}"
|
270
|
+
title += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
233
271
|
$0 = title
|
234
272
|
|
235
273
|
Signal.trap "SIGINT", "IGNORE"
|
@@ -267,6 +305,7 @@ module Puma
|
|
267
305
|
begin
|
268
306
|
@worker_write << "b#{Process.pid}\n"
|
269
307
|
rescue SystemCallError, IOError
|
308
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
270
309
|
STDERR.puts "Master seems to have exited, exiting."
|
271
310
|
return
|
272
311
|
end
|
@@ -275,13 +314,16 @@ module Puma
|
|
275
314
|
base_payload = "p#{Process.pid}"
|
276
315
|
|
277
316
|
while true
|
278
|
-
sleep WORKER_CHECK_INTERVAL
|
317
|
+
sleep Const::WORKER_CHECK_INTERVAL
|
279
318
|
begin
|
280
|
-
b = server.backlog
|
281
|
-
r = server.running
|
282
|
-
|
319
|
+
b = server.backlog || 0
|
320
|
+
r = server.running || 0
|
321
|
+
t = server.pool_capacity || 0
|
322
|
+
m = server.max_threads || 0
|
323
|
+
payload = %Q!#{base_payload}{ "backlog":#{b}, "running":#{r}, "pool_capacity":#{t}, "max_threads": #{m} }\n!
|
283
324
|
io << payload
|
284
325
|
rescue IOError
|
326
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
285
327
|
break
|
286
328
|
end
|
287
329
|
end
|
@@ -337,8 +379,8 @@ module Puma
|
|
337
379
|
def stats
|
338
380
|
old_worker_count = @workers.count { |w| w.phase != @phase }
|
339
381
|
booted_worker_count = @workers.count { |w| w.booted? }
|
340
|
-
worker_status = '[' + @workers.map{ |w| %Q!{ "pid": #{w.pid}, "index": #{w.index}, "phase": #{w.phase}, "booted": #{w.booted?}, "last_checkin": "#{w.last_checkin.utc.iso8601}", "last_status": #{w.last_status} }!}.join(",") + ']'
|
341
|
-
%Q!{ "workers": #{@workers.size}, "phase": #{@phase}, "booted_workers": #{booted_worker_count}, "old_workers": #{old_worker_count}, "worker_status": #{worker_status} }!
|
382
|
+
worker_status = '[' + @workers.map { |w| %Q!{ "started_at": "#{w.started_at.utc.iso8601}", "pid": #{w.pid}, "index": #{w.index}, "phase": #{w.phase}, "booted": #{w.booted?}, "last_checkin": "#{w.last_checkin.utc.iso8601}", "last_status": #{w.last_status} }!}.join(",") + ']'
|
383
|
+
%Q!{ "started_at": "#{@started_at.utc.iso8601}", "workers": #{@workers.size}, "phase": #{@phase}, "booted_workers": #{booted_worker_count}, "old_workers": #{old_worker_count}, "worker_status": #{worker_status} }!
|
342
384
|
end
|
343
385
|
|
344
386
|
def preload?
|
@@ -372,7 +414,13 @@ module Puma
|
|
372
414
|
log "Early termination of worker"
|
373
415
|
exit! 0
|
374
416
|
else
|
417
|
+
@launcher.close_binder_listeners
|
418
|
+
|
419
|
+
stop_workers
|
375
420
|
stop
|
421
|
+
|
422
|
+
raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
|
423
|
+
exit 0 # Clean exit, workers were stopped
|
376
424
|
end
|
377
425
|
end
|
378
426
|
end
|
@@ -466,7 +514,7 @@ module Puma
|
|
466
514
|
|
467
515
|
force_check = false
|
468
516
|
|
469
|
-
res = IO.select([read], nil, nil, WORKER_CHECK_INTERVAL)
|
517
|
+
res = IO.select([read], nil, nil, Const::WORKER_CHECK_INTERVAL)
|
470
518
|
|
471
519
|
if res
|
472
520
|
req = read.read_nonblock(1)
|
data/lib/puma/commonlogger.rb
CHANGED
data/lib/puma/configuration.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puma/rack/builder'
|
2
4
|
require 'puma/plugin'
|
3
5
|
require 'puma/const'
|
@@ -13,152 +15,147 @@ module Puma
|
|
13
15
|
DefaultWorkerShutdownTimeout = 30
|
14
16
|
end
|
15
17
|
|
16
|
-
class
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
18
|
+
# A class used for storing "leveled" configuration options.
|
19
|
+
#
|
20
|
+
# In this class any "user" specified options take precedence over any
|
21
|
+
# "file" specified options, take precedence over any "default" options.
|
22
|
+
#
|
23
|
+
# User input is preferred over "defaults":
|
24
|
+
# user_options = { foo: "bar" }
|
25
|
+
# default_options = { foo: "zoo" }
|
26
|
+
# options = UserFileDefaultOptions.new(user_options, default_options)
|
27
|
+
# puts options[:foo]
|
28
|
+
# # => "bar"
|
29
|
+
#
|
30
|
+
# All values can be accessed via `all_of`
|
31
|
+
#
|
32
|
+
# puts options.all_of(:foo)
|
33
|
+
# # => ["bar", "zoo"]
|
34
|
+
#
|
35
|
+
# A "file" option can be set. This config will be preferred over "default" options
|
36
|
+
# but will defer to any available "user" specified options.
|
37
|
+
#
|
38
|
+
# user_options = { foo: "bar" }
|
39
|
+
# default_options = { rackup: "zoo.rb" }
|
40
|
+
# options = UserFileDefaultOptions.new(user_options, default_options)
|
41
|
+
# options.file_options[:rackup] = "sup.rb"
|
42
|
+
# puts options[:rackup]
|
43
|
+
# # => "sup.rb"
|
44
|
+
#
|
45
|
+
# The "default" options can be set via procs. These are resolved during runtime
|
46
|
+
# via calls to `finalize_values`
|
47
|
+
class UserFileDefaultOptions
|
48
|
+
def initialize(user_options, default_options)
|
49
|
+
@user_options = user_options
|
50
|
+
@file_options = {}
|
51
|
+
@default_options = default_options
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_reader :user_options, :file_options, :default_options
|
37
55
|
|
38
56
|
def [](key)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
v = @defaults[key]
|
46
|
-
if v.respond_to? :call
|
47
|
-
v.call
|
48
|
-
else
|
49
|
-
v
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def fetch(key, default=nil)
|
54
|
-
val = self[key]
|
55
|
-
return val if val
|
56
|
-
default
|
57
|
-
end
|
58
|
-
|
59
|
-
attr_reader :cur
|
60
|
-
|
61
|
-
def all_of(key)
|
62
|
-
all = []
|
63
|
-
|
64
|
-
@set.each do |o|
|
65
|
-
if v = o[key]
|
66
|
-
if v.kind_of? Array
|
67
|
-
all += v
|
68
|
-
else
|
69
|
-
all << v
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
all
|
75
|
-
end
|
76
|
-
|
77
|
-
def []=(key, val)
|
78
|
-
@cur[key] = val
|
57
|
+
return user_options[key] if user_options.key?(key)
|
58
|
+
return file_options[key] if file_options.key?(key)
|
59
|
+
return default_options[key] if default_options.key?(key)
|
79
60
|
end
|
80
61
|
|
81
|
-
def
|
82
|
-
|
83
|
-
if o.key? key
|
84
|
-
return true
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
@default.key? key
|
62
|
+
def []=(key, value)
|
63
|
+
user_options[key] = value
|
89
64
|
end
|
90
65
|
|
91
|
-
def
|
92
|
-
|
93
|
-
@cur[k]= v
|
94
|
-
end
|
66
|
+
def fetch(key, default_value = nil)
|
67
|
+
self[key] || default_value
|
95
68
|
end
|
96
69
|
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
o.each do |k,v|
|
102
|
-
options[k] ||= v
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
options
|
107
|
-
end
|
70
|
+
def all_of(key)
|
71
|
+
user = user_options[key]
|
72
|
+
file = file_options[key]
|
73
|
+
default = default_options[key]
|
108
74
|
|
109
|
-
|
110
|
-
|
75
|
+
user = [user] unless user.is_a?(Array)
|
76
|
+
file = [file] unless file.is_a?(Array)
|
77
|
+
default = [default] unless default.is_a?(Array)
|
111
78
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
79
|
+
user.compact!
|
80
|
+
file.compact!
|
81
|
+
default.compact!
|
116
82
|
|
117
|
-
|
118
|
-
end
|
83
|
+
user + file + default
|
119
84
|
end
|
120
85
|
|
121
|
-
def
|
122
|
-
@
|
86
|
+
def finalize_values
|
87
|
+
@default_options.each do |k,v|
|
123
88
|
if v.respond_to? :call
|
124
|
-
@
|
89
|
+
@default_options[k] = v.call
|
125
90
|
end
|
126
91
|
end
|
127
92
|
end
|
128
93
|
end
|
129
94
|
|
95
|
+
# The main configuration class of Puma.
|
96
|
+
#
|
97
|
+
# It can be initialized with a set of "user" options and "default" options.
|
98
|
+
# Defaults will be merged with `Configuration.puma_default_options`.
|
99
|
+
#
|
100
|
+
# This class works together with 2 main other classes the `UserFileDefaultOptions`
|
101
|
+
# which stores configuration options in order so the precedence is that user
|
102
|
+
# set configuration wins over "file" based configuration wins over "default"
|
103
|
+
# configuration. These configurations are set via the `DSL` class. This
|
104
|
+
# class powers the Puma config file syntax and does double duty as a configuration
|
105
|
+
# DSL used by the `Puma::CLI` and Puma rack handler.
|
106
|
+
#
|
107
|
+
# It also handles loading plugins.
|
108
|
+
#
|
109
|
+
# > Note: `:port` and `:host` are not valid keys. By they time they make it to the
|
110
|
+
# configuration options they are expected to be incorporated into a `:binds` key.
|
111
|
+
# Under the hood the DSL maps `port` and `host` calls to `:binds`
|
112
|
+
#
|
113
|
+
# config = Configuration.new({}) do |user_config, file_config, default_config|
|
114
|
+
# user_config.port 3003
|
115
|
+
# end
|
116
|
+
# config.load
|
117
|
+
# puts config.options[:port]
|
118
|
+
# # => 3003
|
119
|
+
#
|
120
|
+
# It is expected that `load` is called on the configuration instance after setting
|
121
|
+
# config. This method expands any values in `config_file` and puts them into the
|
122
|
+
# correct configuration option hash.
|
123
|
+
#
|
124
|
+
# Once all configuration is complete it is expected that `clamp` will be called
|
125
|
+
# on the instance. This will expand any procs stored under "default" values. This
|
126
|
+
# is done because an environment variable may have been modified while loading
|
127
|
+
# configuration files.
|
130
128
|
class Configuration
|
131
129
|
include ConfigDefault
|
132
130
|
|
133
|
-
def
|
134
|
-
|
131
|
+
def initialize(user_options={}, default_options = {}, &block)
|
132
|
+
default_options = self.puma_default_options.merge(default_options)
|
135
133
|
|
136
|
-
|
134
|
+
@options = UserFileDefaultOptions.new(user_options, default_options)
|
135
|
+
@plugins = PluginLoader.new
|
136
|
+
@user_dsl = DSL.new(@options.user_options, self)
|
137
|
+
@file_dsl = DSL.new(@options.file_options, self)
|
138
|
+
@default_dsl = DSL.new(@options.default_options, self)
|
137
139
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
def initialize(options={}, &blk)
|
142
|
-
@options = LeveledOptions.new(default_options, options)
|
143
|
-
|
144
|
-
@plugins = PluginLoader.new
|
145
|
-
|
146
|
-
if blk
|
147
|
-
configure(&blk)
|
140
|
+
if block
|
141
|
+
configure(&block)
|
148
142
|
end
|
149
143
|
end
|
150
144
|
|
151
145
|
attr_reader :options, :plugins
|
152
146
|
|
153
|
-
def configure
|
154
|
-
@
|
155
|
-
|
147
|
+
def configure
|
148
|
+
yield @user_dsl, @file_dsl, @default_dsl
|
149
|
+
ensure
|
150
|
+
@user_dsl._offer_plugins
|
151
|
+
@file_dsl._offer_plugins
|
152
|
+
@default_dsl._offer_plugins
|
156
153
|
end
|
157
154
|
|
158
155
|
def initialize_copy(other)
|
159
|
-
@conf
|
156
|
+
@conf = nil
|
160
157
|
@cli_options = nil
|
161
|
-
@options
|
158
|
+
@options = @options.dup
|
162
159
|
end
|
163
160
|
|
164
161
|
def flatten
|
@@ -170,7 +167,7 @@ module Puma
|
|
170
167
|
self
|
171
168
|
end
|
172
169
|
|
173
|
-
def
|
170
|
+
def puma_default_options
|
174
171
|
{
|
175
172
|
:min_threads => 0,
|
176
173
|
:max_threads => 16,
|
@@ -185,39 +182,38 @@ module Puma
|
|
185
182
|
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
186
183
|
:remote_address => :socket,
|
187
184
|
:tag => method(:infer_tag),
|
188
|
-
:environment =>
|
185
|
+
:environment => -> { ENV['RACK_ENV'] || "development" },
|
189
186
|
:rackup => DefaultRackup,
|
190
187
|
:logger => STDOUT,
|
191
|
-
:persistent_timeout => Const::PERSISTENT_TIMEOUT
|
188
|
+
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
189
|
+
:first_data_timeout => Const::FIRST_DATA_TIMEOUT,
|
190
|
+
:raise_exception_on_sigterm => true
|
192
191
|
}
|
193
192
|
end
|
194
193
|
|
195
194
|
def load
|
196
|
-
|
195
|
+
config_files.each { |config_file| @file_dsl._load_from(config_file) }
|
197
196
|
|
198
|
-
|
199
|
-
|
200
|
-
File.exist?(f)
|
201
|
-
}
|
197
|
+
@options
|
198
|
+
end
|
202
199
|
|
203
|
-
|
204
|
-
|
205
|
-
files = []
|
206
|
-
end
|
200
|
+
def config_files
|
201
|
+
files = @options.all_of(:config_files)
|
207
202
|
|
208
|
-
files
|
209
|
-
|
203
|
+
return [] if files == ['-']
|
204
|
+
return files if files.any?
|
210
205
|
|
211
|
-
|
206
|
+
first_default_file = %W(config/puma/#{environment_str}.rb config/puma.rb).find do |f|
|
207
|
+
File.exist?(f)
|
212
208
|
end
|
213
|
-
|
209
|
+
|
210
|
+
[first_default_file]
|
214
211
|
end
|
215
212
|
|
216
213
|
# Call once all configuration (included from rackup files)
|
217
214
|
# is loaded to flesh out any defaults
|
218
215
|
def clamp
|
219
|
-
@options.
|
220
|
-
@options.force_defaults
|
216
|
+
@options.finalize_values
|
221
217
|
end
|
222
218
|
|
223
219
|
# Injects the Configuration object into the env
|
@@ -271,6 +267,10 @@ module Puma
|
|
271
267
|
@options[:environment]
|
272
268
|
end
|
273
269
|
|
270
|
+
def environment_str
|
271
|
+
environment.respond_to?(:call) ? environment.call : environment
|
272
|
+
end
|
273
|
+
|
274
274
|
def load_plugin(name)
|
275
275
|
@plugins.create name
|
276
276
|
end
|
@@ -318,17 +318,15 @@ module Puma
|
|
318
318
|
def load_rackup
|
319
319
|
raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
|
320
320
|
|
321
|
-
@options.shift
|
322
|
-
|
323
321
|
rack_app, rack_options = rack_builder.parse_file(rackup)
|
324
|
-
@options.merge!(rack_options)
|
322
|
+
@options.file_options.merge!(rack_options)
|
325
323
|
|
326
324
|
config_ru_binds = []
|
327
325
|
rack_options.each do |k, v|
|
328
326
|
config_ru_binds << v if k.to_s.start_with?("bind")
|
329
327
|
end
|
330
328
|
|
331
|
-
@options[:binds] = config_ru_binds unless config_ru_binds.empty?
|
329
|
+
@options.file_options[:binds] = config_ru_binds unless config_ru_binds.empty?
|
332
330
|
|
333
331
|
rack_app
|
334
332
|
end
|
@@ -350,7 +348,7 @@ module Puma
|
|
350
348
|
end
|
351
349
|
|
352
350
|
if bytes
|
353
|
-
token = ""
|
351
|
+
token = "".dup
|
354
352
|
bytes.each_byte { |b| token << b.to_s(16) }
|
355
353
|
else
|
356
354
|
token = (0..count).to_a.map { rand(255).to_s(16) }.join
|