puma 5.6.4 → 6.3.1
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 +4 -4
- data/History.md +275 -4
- data/LICENSE +0 -0
- data/README.md +60 -20
- data/bin/puma-wild +1 -1
- data/docs/architecture.md +0 -0
- data/docs/compile_options.md +34 -0
- data/docs/deployment.md +0 -0
- data/docs/fork_worker.md +1 -3
- 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/jungle/README.md +0 -0
- data/docs/jungle/rc.d/README.md +0 -0
- data/docs/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +0 -0
- data/docs/nginx.md +1 -1
- data/docs/plugins.md +0 -0
- data/docs/rails_dev_mode.md +0 -0
- data/docs/restart.md +0 -0
- data/docs/signals.md +0 -0
- data/docs/stats.md +0 -0
- data/docs/systemd.md +1 -2
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/ext_help.h +0 -0
- data/ext/puma_http11/extconf.rb +18 -10
- 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 +93 -26
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
- 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 +166 -65
- data/ext/puma_http11/puma_http11.c +17 -9
- data/lib/puma/app/status.rb +7 -4
- data/lib/puma/binder.rb +49 -52
- data/lib/puma/cli.rb +12 -18
- data/lib/puma/client.rb +69 -23
- data/lib/puma/cluster/worker.rb +18 -11
- data/lib/puma/cluster/worker_handle.rb +4 -1
- data/lib/puma/cluster.rb +33 -30
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +76 -58
- data/lib/puma/const.rb +129 -92
- data/lib/puma/control_cli.rb +21 -18
- data/lib/puma/detect.rb +4 -0
- data/lib/puma/dsl.rb +187 -49
- 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/json_serialization.rb +0 -0
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +113 -175
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +24 -12
- data/lib/puma/minissl.rb +108 -15
- data/lib/puma/null_io.rb +5 -0
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/plugin.rb +0 -0
- data/lib/puma/rack/builder.rb +6 -6
- data/lib/puma/rack/urlmap.rb +0 -0
- data/lib/puma/rack_default.rb +19 -4
- data/lib/puma/reactor.rb +19 -10
- data/lib/puma/request.rb +365 -166
- data/lib/puma/runner.rb +52 -20
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +73 -73
- data/lib/puma/single.rb +13 -11
- data/lib/puma/state_file.rb +2 -4
- data/lib/puma/thread_pool.rb +23 -19
- data/lib/puma/util.rb +12 -14
- data/lib/puma.rb +12 -11
- data/lib/rack/handler/puma.rb +113 -86
- data/tools/Dockerfile +0 -0
- data/tools/trickletest.rb +0 -0
- metadata +10 -5
- data/lib/puma/queue_close.rb +0 -26
- data/lib/puma/systemd.rb +0 -46
data/lib/puma/cluster/worker.rb
CHANGED
@@ -2,27 +2,29 @@
|
|
2
2
|
|
3
3
|
module Puma
|
4
4
|
class Cluster < Puma::Runner
|
5
|
+
#—————————————————————— DO NOT USE — this class is for internal use only ———
|
6
|
+
|
7
|
+
|
5
8
|
# This class is instantiated by the `Puma::Cluster` and represents a single
|
6
9
|
# worker process.
|
7
10
|
#
|
8
11
|
# At the core of this class is running an instance of `Puma::Server` which
|
9
12
|
# gets created via the `start_server` method from the `Puma::Runner` class
|
10
13
|
# that this inherits from.
|
11
|
-
class Worker < Puma::Runner
|
14
|
+
class Worker < Puma::Runner # :nodoc:
|
12
15
|
attr_reader :index, :master
|
13
16
|
|
14
17
|
def initialize(index:, master:, launcher:, pipes:, server: nil)
|
15
|
-
super
|
18
|
+
super(launcher)
|
16
19
|
|
17
20
|
@index = index
|
18
21
|
@master = master
|
19
|
-
@launcher = launcher
|
20
|
-
@options = launcher.options
|
21
22
|
@check_pipe = pipes[:check_pipe]
|
22
23
|
@worker_write = pipes[:worker_write]
|
23
24
|
@fork_pipe = pipes[:fork_pipe]
|
24
25
|
@wakeup = pipes[:wakeup]
|
25
26
|
@server = server
|
27
|
+
@hook_data = {}
|
26
28
|
end
|
27
29
|
|
28
30
|
def run
|
@@ -52,13 +54,14 @@ module Puma
|
|
52
54
|
|
53
55
|
# Invoke any worker boot hooks so they can get
|
54
56
|
# things in shape before booting the app.
|
55
|
-
@
|
57
|
+
@config.run_hooks(:before_worker_boot, index, @log_writer, @hook_data)
|
56
58
|
|
57
59
|
begin
|
58
60
|
server = @server ||= start_server
|
59
61
|
rescue Exception => e
|
60
62
|
log "! Unable to start worker"
|
61
|
-
log e
|
63
|
+
log e
|
64
|
+
log e.backtrace.join("\n ")
|
62
65
|
exit 1
|
63
66
|
end
|
64
67
|
|
@@ -83,8 +86,7 @@ module Puma
|
|
83
86
|
if restart_server.length > 0
|
84
87
|
restart_server.clear
|
85
88
|
server.begin_restart(true)
|
86
|
-
@
|
87
|
-
Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
|
89
|
+
@config.run_hooks(:before_refork, nil, @log_writer, @hook_data)
|
88
90
|
end
|
89
91
|
elsif idx == 0 # restart server
|
90
92
|
restart_server << true << false
|
@@ -113,6 +115,11 @@ module Puma
|
|
113
115
|
|
114
116
|
while restart_server.pop
|
115
117
|
server_thread = server.run
|
118
|
+
|
119
|
+
if @log_writer.debug? && index == 0
|
120
|
+
debug_loaded_extensions "Loaded Extensions - worker 0:"
|
121
|
+
end
|
122
|
+
|
116
123
|
stat_thread ||= Thread.new(@worker_write) do |io|
|
117
124
|
Puma.set_thread_name "stat pld"
|
118
125
|
base_payload = "p#{Process.pid}"
|
@@ -138,7 +145,7 @@ module Puma
|
|
138
145
|
|
139
146
|
# Invoke any worker shutdown hooks so they can prevent the worker
|
140
147
|
# exiting until any background operations are completed
|
141
|
-
@
|
148
|
+
@config.run_hooks(:before_worker_shutdown, index, @log_writer, @hook_data)
|
142
149
|
ensure
|
143
150
|
@worker_write << "t#{Process.pid}\n" rescue nil
|
144
151
|
@worker_write.close
|
@@ -147,7 +154,7 @@ module Puma
|
|
147
154
|
private
|
148
155
|
|
149
156
|
def spawn_worker(idx)
|
150
|
-
@
|
157
|
+
@config.run_hooks(:before_worker_fork, idx, @log_writer, @hook_data)
|
151
158
|
|
152
159
|
pid = fork do
|
153
160
|
new_worker = Worker.new index: idx,
|
@@ -165,7 +172,7 @@ module Puma
|
|
165
172
|
exit! 1
|
166
173
|
end
|
167
174
|
|
168
|
-
@
|
175
|
+
@config.run_hooks(:after_worker_fork, idx, @log_writer, @hook_data)
|
169
176
|
pid
|
170
177
|
end
|
171
178
|
end
|
@@ -2,12 +2,15 @@
|
|
2
2
|
|
3
3
|
module Puma
|
4
4
|
class Cluster < Runner
|
5
|
+
#—————————————————————— DO NOT USE — this class is for internal use only ———
|
6
|
+
|
7
|
+
|
5
8
|
# This class represents a worker process from the perspective of the puma
|
6
9
|
# master process. It contains information about the process and its health
|
7
10
|
# and it exposes methods to control the process via IPC. It does not
|
8
11
|
# include the actual logic executed by the worker process itself. For that,
|
9
12
|
# see Puma::Cluster::Worker.
|
10
|
-
class WorkerHandle
|
13
|
+
class WorkerHandle # :nodoc:
|
11
14
|
def initialize(idx, pid, phase, options)
|
12
15
|
@index = idx
|
13
16
|
@pid = pid
|
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 }
|
@@ -92,7 +94,7 @@ module Puma
|
|
92
94
|
|
93
95
|
# @version 5.0.0
|
94
96
|
def spawn_worker(idx, master)
|
95
|
-
@
|
97
|
+
@config.run_hooks(:before_worker_fork, idx, @log_writer)
|
96
98
|
|
97
99
|
pid = fork { worker(idx, master) }
|
98
100
|
if !pid
|
@@ -101,7 +103,7 @@ module Puma
|
|
101
103
|
exit! 1
|
102
104
|
end
|
103
105
|
|
104
|
-
@
|
106
|
+
@config.run_hooks(:after_worker_fork, idx, @log_writer)
|
105
107
|
pid
|
106
108
|
end
|
107
109
|
|
@@ -176,10 +178,10 @@ module Puma
|
|
176
178
|
end
|
177
179
|
end
|
178
180
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
].compact.min
|
181
|
+
t = @workers.reject(&:term?)
|
182
|
+
t.map!(&:ping_timeout)
|
183
|
+
|
184
|
+
@next_check = [t.min, @next_check].compact.min
|
183
185
|
end
|
184
186
|
|
185
187
|
def worker(index, master)
|
@@ -209,8 +211,8 @@ module Puma
|
|
209
211
|
stop
|
210
212
|
end
|
211
213
|
|
212
|
-
def phased_restart
|
213
|
-
return false if @options[:preload_app]
|
214
|
+
def phased_restart(refork = false)
|
215
|
+
return false if @options[:preload_app] && !refork
|
214
216
|
|
215
217
|
@phased_restart = true
|
216
218
|
wakeup!
|
@@ -226,7 +228,7 @@ module Puma
|
|
226
228
|
def stop_blocked
|
227
229
|
@status = :stop if @status == :run
|
228
230
|
wakeup!
|
229
|
-
@control
|
231
|
+
@control&.stop true
|
230
232
|
Process.waitall
|
231
233
|
end
|
232
234
|
|
@@ -248,24 +250,24 @@ module Puma
|
|
248
250
|
old_worker_count = @workers.count { |w| w.phase != @phase }
|
249
251
|
worker_status = @workers.map do |w|
|
250
252
|
{
|
251
|
-
started_at: w.started_at
|
253
|
+
started_at: utc_iso8601(w.started_at),
|
252
254
|
pid: w.pid,
|
253
255
|
index: w.index,
|
254
256
|
phase: w.phase,
|
255
257
|
booted: w.booted?,
|
256
|
-
last_checkin: w.last_checkin
|
258
|
+
last_checkin: utc_iso8601(w.last_checkin),
|
257
259
|
last_status: w.last_status,
|
258
260
|
}
|
259
261
|
end
|
260
262
|
|
261
263
|
{
|
262
|
-
started_at: @started_at
|
264
|
+
started_at: utc_iso8601(@started_at),
|
263
265
|
workers: @workers.size,
|
264
266
|
phase: @phase,
|
265
267
|
booted_workers: worker_status.count { |w| w[:booted] },
|
266
268
|
old_workers: old_worker_count,
|
267
269
|
worker_status: worker_status,
|
268
|
-
}
|
270
|
+
}.merge(super)
|
269
271
|
end
|
270
272
|
|
271
273
|
def preload?
|
@@ -277,7 +279,7 @@ module Puma
|
|
277
279
|
if (worker = @workers.find { |w| w.index == 0 })
|
278
280
|
worker.phase += 1
|
279
281
|
end
|
280
|
-
phased_restart
|
282
|
+
phased_restart(true)
|
281
283
|
end
|
282
284
|
|
283
285
|
# We do this in a separate method to keep the lambda scope
|
@@ -290,7 +292,7 @@ module Puma
|
|
290
292
|
|
291
293
|
# Auto-fork after the specified number of requests.
|
292
294
|
if (fork_requests = @options[:fork_worker].to_i) > 0
|
293
|
-
@
|
295
|
+
@events.register(:ping!) do |w|
|
294
296
|
fork_worker! if w.index == 0 &&
|
295
297
|
w.phase == 0 &&
|
296
298
|
w.last_status[:requests_count] >= fork_requests
|
@@ -372,12 +374,12 @@ module Puma
|
|
372
374
|
else
|
373
375
|
log "* Restarts: (\u2714) hot (\u2714) phased"
|
374
376
|
|
375
|
-
unless @
|
377
|
+
unless @config.app_configured?
|
376
378
|
error "No application configured, nothing to run"
|
377
379
|
exit 1
|
378
380
|
end
|
379
381
|
|
380
|
-
@launcher.binder.parse @options[:binds]
|
382
|
+
@launcher.binder.parse @options[:binds]
|
381
383
|
end
|
382
384
|
|
383
385
|
read, @wakeup = Puma::Util.pipe
|
@@ -409,8 +411,7 @@ module Puma
|
|
409
411
|
|
410
412
|
@master_read, @worker_write = read, @wakeup
|
411
413
|
|
412
|
-
@
|
413
|
-
Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
|
414
|
+
@config.run_hooks(:before_fork, nil, @log_writer)
|
414
415
|
|
415
416
|
spawn_workers
|
416
417
|
|
@@ -463,9 +464,10 @@ module Puma
|
|
463
464
|
w.term unless w.term?
|
464
465
|
when "p"
|
465
466
|
w.ping!(result.sub(/^\d+/,'').chomp)
|
466
|
-
@
|
467
|
+
@events.fire(:ping!, w)
|
467
468
|
if !booted && @workers.none? {|worker| worker.last_status.empty?}
|
468
|
-
@
|
469
|
+
@events.fire_on_booted!
|
470
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
469
471
|
booted = true
|
470
472
|
end
|
471
473
|
end
|
@@ -475,6 +477,7 @@ module Puma
|
|
475
477
|
end
|
476
478
|
if in_phased_restart && workers_not_booted.zero?
|
477
479
|
@events.fire_on_booted!
|
480
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
478
481
|
in_phased_restart = false
|
479
482
|
end
|
480
483
|
|
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
|
+
# note that dsl is loaded at end of file, requires ConfigDefault constants
|
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,50 @@ 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
|
+
io_selector_backend: :auto,
|
139
|
+
log_requests: false,
|
140
|
+
logger: STDOUT,
|
141
|
+
# How many requests to attempt inline before sending a client back to
|
142
|
+
# the reactor to be subject to normal ordering. The idea here is that
|
143
|
+
# we amortize the cost of going back to the reactor for a well behaved
|
144
|
+
# but very "greedy" client across 10 requests. This prevents a not
|
145
|
+
# well behaved client from monopolizing the thread forever.
|
146
|
+
max_fast_inline: 10,
|
147
|
+
max_threads: Puma.mri? ? 5 : 16,
|
148
|
+
min_threads: 0,
|
149
|
+
mode: :http,
|
150
|
+
mutate_stdout_and_stderr_to_sync_on_write: true,
|
151
|
+
out_of_band: [],
|
152
|
+
# Number of seconds for another request within a persistent session.
|
153
|
+
persistent_timeout: 20,
|
154
|
+
queue_requests: true,
|
155
|
+
rackup: 'config.ru'.freeze,
|
156
|
+
raise_exception_on_sigterm: true,
|
157
|
+
reaping_time: 1,
|
158
|
+
remote_address: :socket,
|
159
|
+
silence_single_worker_warning: false,
|
160
|
+
silence_fork_callback_warning: false,
|
161
|
+
tag: File.basename(Dir.getwd),
|
162
|
+
tcp_host: '0.0.0.0'.freeze,
|
163
|
+
tcp_port: 9292,
|
164
|
+
wait_for_less_busy_worker: 0.005,
|
165
|
+
worker_boot_timeout: 60,
|
166
|
+
worker_check_interval: 5,
|
167
|
+
worker_culling_strategy: :youngest,
|
168
|
+
worker_shutdown_timeout: 30,
|
169
|
+
worker_timeout: 60,
|
170
|
+
workers: 0,
|
171
|
+
http_content_length_limit: nil
|
172
|
+
}
|
140
173
|
|
141
174
|
def initialize(user_options={}, default_options = {}, &block)
|
142
175
|
default_options = self.puma_default_options.merge(default_options)
|
@@ -181,37 +214,22 @@ module Puma
|
|
181
214
|
self
|
182
215
|
end
|
183
216
|
|
184
|
-
|
185
|
-
|
186
|
-
|
217
|
+
def puma_default_options
|
218
|
+
defaults = DEFAULTS.dup
|
219
|
+
puma_options_from_env.each { |k,v| defaults[k] = v if v }
|
220
|
+
defaults
|
187
221
|
end
|
188
222
|
|
189
|
-
def
|
223
|
+
def puma_options_from_env
|
224
|
+
min = ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS']
|
225
|
+
max = ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS']
|
226
|
+
workers = ENV['WEB_CONCURRENCY']
|
227
|
+
|
190
228
|
{
|
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,
|
229
|
+
min_threads: min && Integer(min),
|
230
|
+
max_threads: max && Integer(max),
|
231
|
+
workers: workers && Integer(workers),
|
232
|
+
environment: ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'],
|
215
233
|
}
|
216
234
|
end
|
217
235
|
|
@@ -227,7 +245,7 @@ module Puma
|
|
227
245
|
return [] if files == ['-']
|
228
246
|
return files if files.any?
|
229
247
|
|
230
|
-
first_default_file = %W(config/puma/#{
|
248
|
+
first_default_file = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find do |f|
|
231
249
|
File.exist?(f)
|
232
250
|
end
|
233
251
|
|
@@ -270,7 +288,7 @@ module Puma
|
|
270
288
|
found = options[:app] || load_rackup
|
271
289
|
|
272
290
|
if @options[:log_requests]
|
273
|
-
|
291
|
+
require_relative 'commonlogger'
|
274
292
|
logger = @options[:logger]
|
275
293
|
found = CommonLogger.new(found, logger)
|
276
294
|
end
|
@@ -283,21 +301,25 @@ module Puma
|
|
283
301
|
@options[:environment]
|
284
302
|
end
|
285
303
|
|
286
|
-
def environment_str
|
287
|
-
environment.respond_to?(:call) ? environment.call : environment
|
288
|
-
end
|
289
|
-
|
290
304
|
def load_plugin(name)
|
291
305
|
@plugins.create name
|
292
306
|
end
|
293
307
|
|
294
|
-
|
308
|
+
# @param key [:Symbol] hook to run
|
309
|
+
# @param arg [Launcher, Int] `:on_restart` passes Launcher
|
310
|
+
#
|
311
|
+
def run_hooks(key, arg, log_writer, hook_data = nil)
|
295
312
|
@options.all_of(key).each do |b|
|
296
313
|
begin
|
297
|
-
b
|
314
|
+
if Array === b
|
315
|
+
hook_data[b[1]] ||= Hash.new
|
316
|
+
b[0].call arg, hook_data[b[1]]
|
317
|
+
else
|
318
|
+
b.call arg
|
319
|
+
end
|
298
320
|
rescue => e
|
299
|
-
|
300
|
-
|
321
|
+
log_writer.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
322
|
+
log_writer.debug e.backtrace.join("\n")
|
301
323
|
end
|
302
324
|
end
|
303
325
|
end
|
@@ -315,10 +337,6 @@ module Puma
|
|
315
337
|
|
316
338
|
private
|
317
339
|
|
318
|
-
def infer_tag
|
319
|
-
File.basename(Dir.getwd)
|
320
|
-
end
|
321
|
-
|
322
340
|
# Load and use the normal Rack builder if we can, otherwise
|
323
341
|
# fallback to our minimal version.
|
324
342
|
def rack_builder
|
@@ -368,4 +386,4 @@ module Puma
|
|
368
386
|
end
|
369
387
|
end
|
370
388
|
|
371
|
-
|
389
|
+
require_relative 'dsl'
|