puma 5.6.7 → 6.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +327 -16
- data/README.md +79 -29
- data/bin/puma-wild +1 -1
- data/docs/compile_options.md +34 -0
- data/docs/fork_worker.md +1 -3
- data/docs/kubernetes.md +12 -0
- data/docs/nginx.md +1 -1
- data/docs/restart.md +1 -0
- data/docs/systemd.md +3 -6
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/extconf.rb +16 -9
- data/ext/puma_http11/http11_parser.c +1 -1
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +2 -2
- data/ext/puma_http11/http11_parser.rl +2 -2
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +127 -19
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +157 -53
- data/ext/puma_http11/puma_http11.c +17 -9
- data/lib/puma/app/status.rb +4 -4
- data/lib/puma/binder.rb +50 -53
- data/lib/puma/cli.rb +16 -18
- data/lib/puma/client.rb +86 -19
- data/lib/puma/cluster/worker.rb +18 -11
- data/lib/puma/cluster/worker_handle.rb +4 -1
- data/lib/puma/cluster.rb +102 -40
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +77 -59
- data/lib/puma/const.rb +129 -92
- data/lib/puma/control_cli.rb +15 -11
- data/lib/puma/detect.rb +7 -4
- data/lib/puma/dsl.rb +250 -56
- data/lib/puma/error_logger.rb +18 -9
- data/lib/puma/events.rb +6 -126
- data/lib/puma/io_buffer.rb +39 -4
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +102 -175
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +26 -12
- data/lib/puma/minissl.rb +104 -11
- data/lib/puma/null_io.rb +16 -2
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/rack/builder.rb +6 -6
- data/lib/puma/rack/urlmap.rb +1 -1
- data/lib/puma/rack_default.rb +19 -4
- data/lib/puma/reactor.rb +19 -10
- data/lib/puma/request.rb +365 -170
- data/lib/puma/runner.rb +56 -20
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +137 -89
- data/lib/puma/single.rb +13 -11
- data/lib/puma/state_file.rb +3 -6
- data/lib/puma/thread_pool.rb +57 -19
- data/lib/puma/util.rb +0 -11
- data/lib/puma.rb +9 -10
- data/lib/rack/handler/puma.rb +113 -86
- data/tools/Dockerfile +2 -2
- metadata +11 -7
- data/lib/puma/queue_close.rb +0 -26
- data/lib/puma/systemd.rb +0 -46
- data/lib/rack/version_restriction.rb +0 -15
data/lib/puma/cluster.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
require 'time'
|
3
|
+
require_relative 'runner'
|
4
|
+
require_relative 'util'
|
5
|
+
require_relative 'plugin'
|
6
|
+
require_relative 'cluster/worker_handle'
|
7
|
+
require_relative 'cluster/worker'
|
10
8
|
|
11
9
|
module Puma
|
12
10
|
# This class is instantiated by the `Puma::Launcher` and used
|
@@ -17,8 +15,8 @@ module Puma
|
|
17
15
|
# via the `spawn_workers` method call. Each worker will have it's own
|
18
16
|
# instance of a `Puma::Server`.
|
19
17
|
class Cluster < Runner
|
20
|
-
def initialize(
|
21
|
-
super
|
18
|
+
def initialize(launcher)
|
19
|
+
super(launcher)
|
22
20
|
|
23
21
|
@phase = 0
|
24
22
|
@workers = []
|
@@ -27,6 +25,10 @@ module Puma
|
|
27
25
|
@phased_restart = false
|
28
26
|
end
|
29
27
|
|
28
|
+
# Returns the list of cluster worker handles.
|
29
|
+
# @return [Array<Puma::Cluster::WorkerHandle>]
|
30
|
+
attr_reader :workers
|
31
|
+
|
30
32
|
def stop_workers
|
31
33
|
log "- Gracefully shutting down workers..."
|
32
34
|
@workers.each { |x| x.term }
|
@@ -83,16 +85,14 @@ module Puma
|
|
83
85
|
@workers << WorkerHandle.new(idx, pid, @phase, @options)
|
84
86
|
end
|
85
87
|
|
86
|
-
if @options[:fork_worker] &&
|
87
|
-
@workers.all? {|x| x.phase == @phase}
|
88
|
-
|
88
|
+
if @options[:fork_worker] && all_workers_in_phase?
|
89
89
|
@fork_writer << "0\n"
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
93
|
# @version 5.0.0
|
94
94
|
def spawn_worker(idx, master)
|
95
|
-
@
|
95
|
+
@config.run_hooks(:before_worker_fork, idx, @log_writer)
|
96
96
|
|
97
97
|
pid = fork { worker(idx, master) }
|
98
98
|
if !pid
|
@@ -101,7 +101,7 @@ module Puma
|
|
101
101
|
exit! 1
|
102
102
|
end
|
103
103
|
|
104
|
-
@
|
104
|
+
@config.run_hooks(:after_worker_fork, idx, @log_writer)
|
105
105
|
pid
|
106
106
|
end
|
107
107
|
|
@@ -146,10 +146,22 @@ module Puma
|
|
146
146
|
idx
|
147
147
|
end
|
148
148
|
|
149
|
+
def worker_at(idx)
|
150
|
+
@workers.find { |w| w.index == idx }
|
151
|
+
end
|
152
|
+
|
149
153
|
def all_workers_booted?
|
150
154
|
@workers.count { |w| !w.booted? } == 0
|
151
155
|
end
|
152
156
|
|
157
|
+
def all_workers_in_phase?
|
158
|
+
@workers.all? { |w| w.phase == @phase }
|
159
|
+
end
|
160
|
+
|
161
|
+
def all_workers_idle_timed_out?
|
162
|
+
(@workers.map(&:pid) - idle_timed_out_worker_pids).empty?
|
163
|
+
end
|
164
|
+
|
153
165
|
def check_workers
|
154
166
|
return if @next_check >= Time.now
|
155
167
|
|
@@ -176,10 +188,10 @@ module Puma
|
|
176
188
|
end
|
177
189
|
end
|
178
190
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
].compact.min
|
191
|
+
t = @workers.reject(&:term?)
|
192
|
+
t.map!(&:ping_timeout)
|
193
|
+
|
194
|
+
@next_check = [t.min, @next_check].compact.min
|
183
195
|
end
|
184
196
|
|
185
197
|
def worker(index, master)
|
@@ -209,8 +221,8 @@ module Puma
|
|
209
221
|
stop
|
210
222
|
end
|
211
223
|
|
212
|
-
def phased_restart
|
213
|
-
return false if @options[:preload_app]
|
224
|
+
def phased_restart(refork = false)
|
225
|
+
return false if @options[:preload_app] && !refork
|
214
226
|
|
215
227
|
@phased_restart = true
|
216
228
|
wakeup!
|
@@ -226,7 +238,7 @@ module Puma
|
|
226
238
|
def stop_blocked
|
227
239
|
@status = :stop if @status == :run
|
228
240
|
wakeup!
|
229
|
-
@control
|
241
|
+
@control&.stop true
|
230
242
|
Process.waitall
|
231
243
|
end
|
232
244
|
|
@@ -248,24 +260,24 @@ module Puma
|
|
248
260
|
old_worker_count = @workers.count { |w| w.phase != @phase }
|
249
261
|
worker_status = @workers.map do |w|
|
250
262
|
{
|
251
|
-
started_at: w.started_at
|
263
|
+
started_at: utc_iso8601(w.started_at),
|
252
264
|
pid: w.pid,
|
253
265
|
index: w.index,
|
254
266
|
phase: w.phase,
|
255
267
|
booted: w.booted?,
|
256
|
-
last_checkin: w.last_checkin
|
268
|
+
last_checkin: utc_iso8601(w.last_checkin),
|
257
269
|
last_status: w.last_status,
|
258
270
|
}
|
259
271
|
end
|
260
272
|
|
261
273
|
{
|
262
|
-
started_at: @started_at
|
274
|
+
started_at: utc_iso8601(@started_at),
|
263
275
|
workers: @workers.size,
|
264
276
|
phase: @phase,
|
265
277
|
booted_workers: worker_status.count { |w| w[:booted] },
|
266
278
|
old_workers: old_worker_count,
|
267
279
|
worker_status: worker_status,
|
268
|
-
}
|
280
|
+
}.merge(super)
|
269
281
|
end
|
270
282
|
|
271
283
|
def preload?
|
@@ -274,10 +286,10 @@ module Puma
|
|
274
286
|
|
275
287
|
# @version 5.0.0
|
276
288
|
def fork_worker!
|
277
|
-
if (worker =
|
289
|
+
if (worker = worker_at 0)
|
278
290
|
worker.phase += 1
|
279
291
|
end
|
280
|
-
phased_restart
|
292
|
+
phased_restart(true)
|
281
293
|
end
|
282
294
|
|
283
295
|
# We do this in a separate method to keep the lambda scope
|
@@ -290,7 +302,7 @@ module Puma
|
|
290
302
|
|
291
303
|
# Auto-fork after the specified number of requests.
|
292
304
|
if (fork_requests = @options[:fork_worker].to_i) > 0
|
293
|
-
@
|
305
|
+
@events.register(:ping!) do |w|
|
294
306
|
fork_worker! if w.index == 0 &&
|
295
307
|
w.phase == 0 &&
|
296
308
|
w.last_status[:requests_count] >= fork_requests
|
@@ -336,6 +348,8 @@ module Puma
|
|
336
348
|
def run
|
337
349
|
@status = :run
|
338
350
|
|
351
|
+
@idle_workers = {}
|
352
|
+
|
339
353
|
output_header "cluster"
|
340
354
|
|
341
355
|
# This is aligned with the output from Runner, see Runner#output_header
|
@@ -372,12 +386,12 @@ module Puma
|
|
372
386
|
else
|
373
387
|
log "* Restarts: (\u2714) hot (\u2714) phased"
|
374
388
|
|
375
|
-
unless @
|
389
|
+
unless @config.app_configured?
|
376
390
|
error "No application configured, nothing to run"
|
377
391
|
exit 1
|
378
392
|
end
|
379
393
|
|
380
|
-
@launcher.binder.parse @options[:binds]
|
394
|
+
@launcher.binder.parse @options[:binds]
|
381
395
|
end
|
382
396
|
|
383
397
|
read, @wakeup = Puma::Util.pipe
|
@@ -409,8 +423,9 @@ module Puma
|
|
409
423
|
|
410
424
|
@master_read, @worker_write = read, @wakeup
|
411
425
|
|
412
|
-
@
|
413
|
-
|
426
|
+
@options[:worker_write] = @worker_write
|
427
|
+
|
428
|
+
@config.run_hooks(:before_fork, nil, @log_writer)
|
414
429
|
|
415
430
|
spawn_workers
|
416
431
|
|
@@ -425,6 +440,11 @@ module Puma
|
|
425
440
|
|
426
441
|
while @status == :run
|
427
442
|
begin
|
443
|
+
if all_workers_idle_timed_out?
|
444
|
+
log "- All workers reached idle timeout"
|
445
|
+
break
|
446
|
+
end
|
447
|
+
|
428
448
|
if @phased_restart
|
429
449
|
start_phased_restart
|
430
450
|
@phased_restart = false
|
@@ -445,7 +465,7 @@ module Puma
|
|
445
465
|
|
446
466
|
if req == "b" || req == "f"
|
447
467
|
pid, idx = result.split(':').map(&:to_i)
|
448
|
-
w =
|
468
|
+
w = worker_at idx
|
449
469
|
w.pid = pid if w.pid.nil?
|
450
470
|
end
|
451
471
|
|
@@ -462,22 +482,37 @@ module Puma
|
|
462
482
|
when "t"
|
463
483
|
w.term unless w.term?
|
464
484
|
when "p"
|
465
|
-
|
466
|
-
|
485
|
+
status = result.sub(/^\d+/,'').chomp
|
486
|
+
w.ping!(status)
|
487
|
+
@events.fire(:ping!, w)
|
488
|
+
|
489
|
+
if in_phased_restart && workers_not_booted.positive? && w0 = worker_at(0)
|
490
|
+
w0.ping!(status)
|
491
|
+
@events.fire(:ping!, w0)
|
492
|
+
end
|
493
|
+
|
467
494
|
if !booted && @workers.none? {|worker| worker.last_status.empty?}
|
468
|
-
@
|
495
|
+
@events.fire_on_booted!
|
496
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
469
497
|
booted = true
|
470
498
|
end
|
499
|
+
when "i"
|
500
|
+
if @idle_workers[pid]
|
501
|
+
@idle_workers.delete pid
|
502
|
+
else
|
503
|
+
@idle_workers[pid] = true
|
504
|
+
end
|
471
505
|
end
|
472
506
|
else
|
473
507
|
log "! Out-of-sync worker list, no #{pid} worker"
|
474
508
|
end
|
475
509
|
end
|
510
|
+
|
476
511
|
if in_phased_restart && workers_not_booted.zero?
|
477
512
|
@events.fire_on_booted!
|
513
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
478
514
|
in_phased_restart = false
|
479
515
|
end
|
480
|
-
|
481
516
|
rescue Interrupt
|
482
517
|
@status = :stop
|
483
518
|
end
|
@@ -506,10 +541,28 @@ module Puma
|
|
506
541
|
# loops thru @workers, removing workers that exited, and calling
|
507
542
|
# `#term` if needed
|
508
543
|
def wait_workers
|
544
|
+
# Reap all children, known workers or otherwise.
|
545
|
+
# If puma has PID 1, as it's common in containerized environments,
|
546
|
+
# then it's responsible for reaping orphaned processes, so we must reap
|
547
|
+
# all our dead children, regardless of whether they are workers we spawned
|
548
|
+
# or some reattached processes.
|
549
|
+
reaped_children = {}
|
550
|
+
loop do
|
551
|
+
begin
|
552
|
+
pid, status = Process.wait2(-1, Process::WNOHANG)
|
553
|
+
break unless pid
|
554
|
+
reaped_children[pid] = status
|
555
|
+
rescue Errno::ECHILD
|
556
|
+
break
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
509
560
|
@workers.reject! do |w|
|
510
561
|
next false if w.pid.nil?
|
511
562
|
begin
|
512
|
-
|
563
|
+
# When `fork_worker` is enabled, some worker may not be direct children, but grand children.
|
564
|
+
# Because of this they won't be reaped by `Process.wait2(-1)`, so we need to check them individually)
|
565
|
+
if reaped_children.delete(w.pid) || (@options[:fork_worker] && Process.wait(w.pid, Process::WNOHANG))
|
513
566
|
true
|
514
567
|
else
|
515
568
|
w.term if w.term?
|
@@ -526,6 +579,11 @@ module Puma
|
|
526
579
|
end
|
527
580
|
end
|
528
581
|
end
|
582
|
+
|
583
|
+
# Log unknown children
|
584
|
+
reaped_children.each do |pid, status|
|
585
|
+
log "! reaped unknown child process pid=#{pid} status=#{status}"
|
586
|
+
end
|
529
587
|
end
|
530
588
|
|
531
589
|
# @version 5.0.0
|
@@ -533,14 +591,18 @@ module Puma
|
|
533
591
|
@workers.each do |w|
|
534
592
|
if !w.term? && w.ping_timeout <= Time.now
|
535
593
|
details = if w.booted?
|
536
|
-
"(
|
594
|
+
"(Worker #{w.index} failed to check in within #{@options[:worker_timeout]} seconds)"
|
537
595
|
else
|
538
|
-
"(
|
596
|
+
"(Worker #{w.index} failed to boot within #{@options[:worker_boot_timeout]} seconds)"
|
539
597
|
end
|
540
598
|
log "! Terminating timed out worker #{details}: #{w.pid}"
|
541
599
|
w.kill
|
542
600
|
end
|
543
601
|
end
|
544
602
|
end
|
603
|
+
|
604
|
+
def idle_timed_out_worker_pids
|
605
|
+
@idle_workers.keys
|
606
|
+
end
|
545
607
|
end
|
546
608
|
end
|
data/lib/puma/commonlogger.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Puma
|
4
4
|
# Rack::CommonLogger forwards every request to the given +app+, and
|
5
5
|
# logs a line in the
|
6
|
-
# {Apache common log format}[https://httpd.apache.org/docs/
|
6
|
+
# {Apache common log format}[https://httpd.apache.org/docs/2.4/logs.html#common]
|
7
7
|
# to the +logger+.
|
8
8
|
#
|
9
9
|
# If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
|
@@ -16,7 +16,7 @@ module Puma
|
|
16
16
|
# (which is called without arguments in order to make the error appear for
|
17
17
|
# sure)
|
18
18
|
class CommonLogger
|
19
|
-
# Common Log Format: https://httpd.apache.org/docs/
|
19
|
+
# Common Log Format: https://httpd.apache.org/docs/2.4/logs.html#common
|
20
20
|
#
|
21
21
|
# lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
|
22
22
|
#
|
@@ -25,10 +25,17 @@ module Puma
|
|
25
25
|
|
26
26
|
HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
LOG_TIME_FORMAT = '%d/%b/%Y:%H:%M:%S %z'
|
29
|
+
|
30
|
+
CONTENT_LENGTH = 'Content-Length' # should be lower case from app,
|
31
|
+
# Util::HeaderHash allows mixed
|
32
|
+
HTTP_VERSION = Const::HTTP_VERSION
|
33
|
+
HTTP_X_FORWARDED_FOR = Const::HTTP_X_FORWARDED_FOR
|
34
|
+
PATH_INFO = Const::PATH_INFO
|
35
|
+
QUERY_STRING = Const::QUERY_STRING
|
36
|
+
REMOTE_ADDR = Const::REMOTE_ADDR
|
37
|
+
REMOTE_USER = 'REMOTE_USER'
|
38
|
+
REQUEST_METHOD = Const::REQUEST_METHOD
|
32
39
|
|
33
40
|
def initialize(app, logger=nil)
|
34
41
|
@app = app
|
@@ -57,13 +64,13 @@ module Puma
|
|
57
64
|
now = Time.now
|
58
65
|
|
59
66
|
msg = HIJACK_FORMAT % [
|
60
|
-
env[
|
61
|
-
env[
|
62
|
-
now.strftime(
|
67
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
68
|
+
env[REMOTE_USER] || "-",
|
69
|
+
now.strftime(LOG_TIME_FORMAT),
|
63
70
|
env[REQUEST_METHOD],
|
64
71
|
env[PATH_INFO],
|
65
72
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
66
|
-
env[
|
73
|
+
env[HTTP_VERSION],
|
67
74
|
now - began_at ]
|
68
75
|
|
69
76
|
write(msg)
|
@@ -74,13 +81,13 @@ module Puma
|
|
74
81
|
length = extract_content_length(header)
|
75
82
|
|
76
83
|
msg = FORMAT % [
|
77
|
-
env[
|
78
|
-
env[
|
79
|
-
now.strftime(
|
84
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
85
|
+
env[REMOTE_USER] || "-",
|
86
|
+
now.strftime(LOG_TIME_FORMAT),
|
80
87
|
env[REQUEST_METHOD],
|
81
88
|
env[PATH_INFO],
|
82
89
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
83
|
-
env[
|
90
|
+
env[HTTP_VERSION],
|
84
91
|
status.to_s[0..3],
|
85
92
|
length,
|
86
93
|
now - began_at ]
|
data/lib/puma/configuration.rb
CHANGED
@@ -1,21 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative 'rack/builder'
|
4
|
+
require_relative 'plugin'
|
5
|
+
require_relative 'const'
|
6
|
+
require_relative 'dsl'
|
6
7
|
|
7
8
|
module Puma
|
8
|
-
|
9
|
-
module ConfigDefault
|
10
|
-
DefaultRackup = "config.ru"
|
11
|
-
|
12
|
-
DefaultTCPHost = "0.0.0.0"
|
13
|
-
DefaultTCPPort = 9292
|
14
|
-
DefaultWorkerCheckInterval = 5
|
15
|
-
DefaultWorkerTimeout = 60
|
16
|
-
DefaultWorkerShutdownTimeout = 30
|
17
|
-
end
|
18
|
-
|
19
9
|
# A class used for storing "leveled" configuration options.
|
20
10
|
#
|
21
11
|
# In this class any "user" specified options take precedence over any
|
@@ -136,7 +126,52 @@ module Puma
|
|
136
126
|
# is done because an environment variable may have been modified while loading
|
137
127
|
# configuration files.
|
138
128
|
class Configuration
|
139
|
-
|
129
|
+
DEFAULTS = {
|
130
|
+
auto_trim_time: 30,
|
131
|
+
binds: ['tcp://0.0.0.0:9292'.freeze],
|
132
|
+
clean_thread_locals: false,
|
133
|
+
debug: false,
|
134
|
+
early_hints: nil,
|
135
|
+
environment: 'development'.freeze,
|
136
|
+
# Number of seconds to wait until we get the first data for the request.
|
137
|
+
first_data_timeout: 30,
|
138
|
+
# Number of seconds to wait until the next request before shutting down.
|
139
|
+
idle_timeout: nil,
|
140
|
+
io_selector_backend: :auto,
|
141
|
+
log_requests: false,
|
142
|
+
logger: STDOUT,
|
143
|
+
# How many requests to attempt inline before sending a client back to
|
144
|
+
# the reactor to be subject to normal ordering. The idea here is that
|
145
|
+
# we amortize the cost of going back to the reactor for a well behaved
|
146
|
+
# but very "greedy" client across 10 requests. This prevents a not
|
147
|
+
# well behaved client from monopolizing the thread forever.
|
148
|
+
max_fast_inline: 10,
|
149
|
+
max_threads: Puma.mri? ? 5 : 16,
|
150
|
+
min_threads: 0,
|
151
|
+
mode: :http,
|
152
|
+
mutate_stdout_and_stderr_to_sync_on_write: true,
|
153
|
+
out_of_band: [],
|
154
|
+
# Number of seconds for another request within a persistent session.
|
155
|
+
persistent_timeout: 20,
|
156
|
+
queue_requests: true,
|
157
|
+
rackup: 'config.ru'.freeze,
|
158
|
+
raise_exception_on_sigterm: true,
|
159
|
+
reaping_time: 1,
|
160
|
+
remote_address: :socket,
|
161
|
+
silence_single_worker_warning: false,
|
162
|
+
silence_fork_callback_warning: false,
|
163
|
+
tag: File.basename(Dir.getwd),
|
164
|
+
tcp_host: '0.0.0.0'.freeze,
|
165
|
+
tcp_port: 9292,
|
166
|
+
wait_for_less_busy_worker: 0.005,
|
167
|
+
worker_boot_timeout: 60,
|
168
|
+
worker_check_interval: 5,
|
169
|
+
worker_culling_strategy: :youngest,
|
170
|
+
worker_shutdown_timeout: 30,
|
171
|
+
worker_timeout: 60,
|
172
|
+
workers: 0,
|
173
|
+
http_content_length_limit: nil
|
174
|
+
}
|
140
175
|
|
141
176
|
def initialize(user_options={}, default_options = {}, &block)
|
142
177
|
default_options = self.puma_default_options.merge(default_options)
|
@@ -181,37 +216,22 @@ module Puma
|
|
181
216
|
self
|
182
217
|
end
|
183
218
|
|
184
|
-
|
185
|
-
|
186
|
-
|
219
|
+
def puma_default_options
|
220
|
+
defaults = DEFAULTS.dup
|
221
|
+
puma_options_from_env.each { |k,v| defaults[k] = v if v }
|
222
|
+
defaults
|
187
223
|
end
|
188
224
|
|
189
|
-
def
|
225
|
+
def puma_options_from_env
|
226
|
+
min = ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS']
|
227
|
+
max = ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS']
|
228
|
+
workers = ENV['WEB_CONCURRENCY']
|
229
|
+
|
190
230
|
{
|
191
|
-
:
|
192
|
-
:
|
193
|
-
:
|
194
|
-
:
|
195
|
-
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
|
196
|
-
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
197
|
-
:silence_single_worker_warning => false,
|
198
|
-
:mode => :http,
|
199
|
-
:worker_check_interval => DefaultWorkerCheckInterval,
|
200
|
-
:worker_timeout => DefaultWorkerTimeout,
|
201
|
-
:worker_boot_timeout => DefaultWorkerTimeout,
|
202
|
-
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
203
|
-
:worker_culling_strategy => :youngest,
|
204
|
-
:remote_address => :socket,
|
205
|
-
:tag => method(:infer_tag),
|
206
|
-
:environment => -> { ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development' },
|
207
|
-
:rackup => DefaultRackup,
|
208
|
-
:logger => STDOUT,
|
209
|
-
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
210
|
-
:first_data_timeout => Const::FIRST_DATA_TIMEOUT,
|
211
|
-
:raise_exception_on_sigterm => true,
|
212
|
-
:max_fast_inline => Const::MAX_FAST_INLINE,
|
213
|
-
:io_selector_backend => :auto,
|
214
|
-
:mutate_stdout_and_stderr_to_sync_on_write => true,
|
231
|
+
min_threads: min && Integer(min),
|
232
|
+
max_threads: max && Integer(max),
|
233
|
+
workers: workers && Integer(workers),
|
234
|
+
environment: ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'],
|
215
235
|
}
|
216
236
|
end
|
217
237
|
|
@@ -227,7 +247,7 @@ module Puma
|
|
227
247
|
return [] if files == ['-']
|
228
248
|
return files if files.any?
|
229
249
|
|
230
|
-
first_default_file = %W(config/puma/#{
|
250
|
+
first_default_file = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find do |f|
|
231
251
|
File.exist?(f)
|
232
252
|
end
|
233
253
|
|
@@ -270,7 +290,7 @@ module Puma
|
|
270
290
|
found = options[:app] || load_rackup
|
271
291
|
|
272
292
|
if @options[:log_requests]
|
273
|
-
|
293
|
+
require_relative 'commonlogger'
|
274
294
|
logger = @options[:logger]
|
275
295
|
found = CommonLogger.new(found, logger)
|
276
296
|
end
|
@@ -283,21 +303,25 @@ module Puma
|
|
283
303
|
@options[:environment]
|
284
304
|
end
|
285
305
|
|
286
|
-
def environment_str
|
287
|
-
environment.respond_to?(:call) ? environment.call : environment
|
288
|
-
end
|
289
|
-
|
290
306
|
def load_plugin(name)
|
291
307
|
@plugins.create name
|
292
308
|
end
|
293
309
|
|
294
|
-
|
310
|
+
# @param key [:Symbol] hook to run
|
311
|
+
# @param arg [Launcher, Int] `:on_restart` passes Launcher
|
312
|
+
#
|
313
|
+
def run_hooks(key, arg, log_writer, hook_data = nil)
|
295
314
|
@options.all_of(key).each do |b|
|
296
315
|
begin
|
297
|
-
b
|
316
|
+
if Array === b
|
317
|
+
hook_data[b[1]] ||= Hash.new
|
318
|
+
b[0].call arg, hook_data[b[1]]
|
319
|
+
else
|
320
|
+
b.call arg
|
321
|
+
end
|
298
322
|
rescue => e
|
299
|
-
|
300
|
-
|
323
|
+
log_writer.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
324
|
+
log_writer.debug e.backtrace.join("\n")
|
301
325
|
end
|
302
326
|
end
|
303
327
|
end
|
@@ -315,10 +339,6 @@ module Puma
|
|
315
339
|
|
316
340
|
private
|
317
341
|
|
318
|
-
def infer_tag
|
319
|
-
File.basename(Dir.getwd)
|
320
|
-
end
|
321
|
-
|
322
342
|
# Load and use the normal Rack builder if we can, otherwise
|
323
343
|
# fallback to our minimal version.
|
324
344
|
def rack_builder
|
@@ -367,5 +387,3 @@ module Puma
|
|
367
387
|
end
|
368
388
|
end
|
369
389
|
end
|
370
|
-
|
371
|
-
require 'puma/dsl'
|