puma 3.12.0 → 5.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.

Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1413 -439
  3. data/LICENSE +23 -20
  4. data/README.md +131 -60
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +24 -19
  7. data/docs/compile_options.md +19 -0
  8. data/docs/deployment.md +38 -13
  9. data/docs/fork_worker.md +33 -0
  10. data/docs/jungle/README.md +9 -0
  11. data/{tools → docs}/jungle/rc.d/README.md +1 -1
  12. data/{tools → docs}/jungle/rc.d/puma +2 -2
  13. data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
  14. data/docs/kubernetes.md +66 -0
  15. data/docs/nginx.md +1 -1
  16. data/docs/plugins.md +20 -10
  17. data/docs/rails_dev_mode.md +29 -0
  18. data/docs/restart.md +47 -22
  19. data/docs/signals.md +7 -6
  20. data/docs/stats.md +142 -0
  21. data/docs/systemd.md +48 -70
  22. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  23. data/ext/puma_http11/ext_help.h +1 -1
  24. data/ext/puma_http11/extconf.rb +27 -0
  25. data/ext/puma_http11/http11_parser.c +84 -109
  26. data/ext/puma_http11/http11_parser.h +1 -1
  27. data/ext/puma_http11/http11_parser.java.rl +22 -38
  28. data/ext/puma_http11/http11_parser.rl +4 -2
  29. data/ext/puma_http11/http11_parser_common.rl +3 -3
  30. data/ext/puma_http11/mini_ssl.c +262 -87
  31. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  32. data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
  33. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +89 -106
  34. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +92 -22
  35. data/ext/puma_http11/puma_http11.c +34 -50
  36. data/lib/puma/app/status.rb +68 -49
  37. data/lib/puma/binder.rb +197 -144
  38. data/lib/puma/cli.rb +17 -15
  39. data/lib/puma/client.rb +257 -226
  40. data/lib/puma/cluster/worker.rb +176 -0
  41. data/lib/puma/cluster/worker_handle.rb +90 -0
  42. data/lib/puma/cluster.rb +223 -212
  43. data/lib/puma/commonlogger.rb +4 -2
  44. data/lib/puma/configuration.rb +58 -51
  45. data/lib/puma/const.rb +41 -19
  46. data/lib/puma/control_cli.rb +117 -73
  47. data/lib/puma/detect.rb +26 -3
  48. data/lib/puma/dsl.rb +531 -123
  49. data/lib/puma/error_logger.rb +104 -0
  50. data/lib/puma/events.rb +57 -31
  51. data/lib/puma/io_buffer.rb +9 -5
  52. data/lib/puma/jruby_restart.rb +2 -58
  53. data/lib/puma/json.rb +96 -0
  54. data/lib/puma/launcher.rb +182 -70
  55. data/lib/puma/minissl/context_builder.rb +79 -0
  56. data/lib/puma/minissl.rb +149 -48
  57. data/lib/puma/null_io.rb +15 -1
  58. data/lib/puma/plugin/tmp_restart.rb +2 -0
  59. data/lib/puma/plugin.rb +8 -12
  60. data/lib/puma/queue_close.rb +26 -0
  61. data/lib/puma/rack/builder.rb +4 -5
  62. data/lib/puma/rack/urlmap.rb +2 -0
  63. data/lib/puma/rack_default.rb +2 -0
  64. data/lib/puma/reactor.rb +87 -316
  65. data/lib/puma/request.rb +456 -0
  66. data/lib/puma/runner.rb +33 -52
  67. data/lib/puma/server.rb +288 -679
  68. data/lib/puma/single.rb +13 -67
  69. data/lib/puma/state_file.rb +10 -3
  70. data/lib/puma/systemd.rb +46 -0
  71. data/lib/puma/thread_pool.rb +131 -81
  72. data/lib/puma/util.rb +14 -6
  73. data/lib/puma.rb +54 -0
  74. data/lib/rack/handler/puma.rb +8 -6
  75. data/tools/Dockerfile +16 -0
  76. data/tools/trickletest.rb +0 -1
  77. metadata +45 -29
  78. data/ext/puma_http11/io_buffer.c +0 -155
  79. data/lib/puma/accept_nonblock.rb +0 -23
  80. data/lib/puma/compat.rb +0 -14
  81. data/lib/puma/convenient.rb +0 -23
  82. data/lib/puma/daemon_ext.rb +0 -31
  83. data/lib/puma/delegation.rb +0 -11
  84. data/lib/puma/java_io_buffer.rb +0 -45
  85. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
  86. data/lib/puma/tcp_logger.rb +0 -39
  87. data/tools/jungle/README.md +0 -19
  88. data/tools/jungle/init.d/README.md +0 -61
  89. data/tools/jungle/init.d/puma +0 -421
  90. data/tools/jungle/init.d/run-puma +0 -18
  91. data/tools/jungle/upstart/README.md +0 -61
  92. data/tools/jungle/upstart/puma-manager.conf +0 -31
  93. data/tools/jungle/upstart/puma.conf +0 -69
data/lib/puma/dsl.rb CHANGED
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/const'
4
+
1
5
  module Puma
2
- # The methods that are available for use inside the config file.
6
+ # The methods that are available for use inside the configuration file.
3
7
  # These same methods are used in Puma cli and the rack handler
4
8
  # internally.
5
9
  #
@@ -10,24 +14,60 @@ module Puma
10
14
  # end
11
15
  # config.load
12
16
  #
13
- # puts config.options[:binds]
14
- # "tcp://127.0.0.1:3001"
17
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3001"
15
18
  #
16
19
  # Used to load file:
17
20
  #
18
21
  # $ cat puma_config.rb
19
- # port 3002
22
+ # port 3002
23
+ #
24
+ # Resulting configuration:
20
25
  #
21
26
  # config = Configuration.new(config_file: "puma_config.rb")
22
27
  # config.load
23
28
  #
24
- # puts config.options[:binds]
25
- # # => "tcp://127.0.0.1:3002"
29
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3002"
30
+ #
31
+ # You can also find many examples being used by the test suite in
32
+ # +test/config+.
26
33
  #
27
- # Detailed docs can be found in `examples/config.rb`
28
34
  class DSL
29
35
  include ConfigDefault
30
36
 
37
+ # convenience method so logic can be used in CI
38
+ # @see ssl_bind
39
+ #
40
+ def self.ssl_bind_str(host, port, opts)
41
+ verify = opts.fetch(:verify_mode, 'none').to_s
42
+
43
+ tls_str =
44
+ if opts[:no_tlsv1_1] then '&no_tlsv1_1=true'
45
+ elsif opts[:no_tlsv1] then '&no_tlsv1=true'
46
+ else ''
47
+ end
48
+
49
+ ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
50
+
51
+ if defined?(JRUBY_VERSION)
52
+ ssl_cipher_list = opts[:ssl_cipher_list] ?
53
+ "&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
54
+
55
+ keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
56
+
57
+ "ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
58
+ "&verify_mode=#{verify}#{tls_str}#{ca_additions}"
59
+ else
60
+ ssl_cipher_filter = opts[:ssl_cipher_filter] ?
61
+ "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
62
+
63
+ v_flags = (ary = opts[:verification_flags]) ?
64
+ "&verification_flags=#{Array(ary).join ','}" : nil
65
+
66
+ "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
67
+ "#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}"
68
+ end
69
+ end
70
+
31
71
  def initialize(options, config)
32
72
  @config = config
33
73
  @options = options
@@ -55,6 +95,14 @@ module Puma
55
95
  @plugins.clear
56
96
  end
57
97
 
98
+ def set_default_host(host)
99
+ @options[:default_host] = host
100
+ end
101
+
102
+ def default_host
103
+ @options[:default_host] || Configuration::DefaultTCPHost
104
+ end
105
+
58
106
  def inject(&blk)
59
107
  instance_eval(&blk)
60
108
  end
@@ -69,8 +117,24 @@ module Puma
69
117
  @plugins << @config.load_plugin(name)
70
118
  end
71
119
 
72
- # Use +obj+ or +block+ as the Rack app. This allows a config file to
73
- # be the app itself.
120
+ # Use an object or block as the rack application. This allows the
121
+ # configuration file to be the application itself.
122
+ #
123
+ # @example
124
+ # app do |env|
125
+ # body = 'Hello, World!'
126
+ #
127
+ # [
128
+ # 200,
129
+ # {
130
+ # 'Content-Type' => 'text/plain',
131
+ # 'Content-Length' => body.length.to_s
132
+ # },
133
+ # [body]
134
+ # ]
135
+ # end
136
+ #
137
+ # @see Puma::Configuration#app
74
138
  #
75
139
  def app(obj=nil, &block)
76
140
  obj ||= block
@@ -80,9 +144,20 @@ module Puma
80
144
  @options[:app] = obj
81
145
  end
82
146
 
83
- # Start the Puma control rack app on +url+. This app can be communicated
84
- # with to control the main server.
147
+ # Start the Puma control rack application on +url+. This application can
148
+ # be communicated with to control the main server. Additionally, you can
149
+ # provide an authentication token, so all requests to the control server
150
+ # will need to include that token as a query parameter. This allows for
151
+ # simple authentication.
152
+ #
153
+ # Check out {Puma::App::Status} to see what the app has available.
85
154
  #
155
+ # @example
156
+ # activate_control_app 'unix:///var/run/pumactl.sock'
157
+ # @example
158
+ # activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
159
+ # @example
160
+ # activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
86
161
  def activate_control_app(url="auto", opts={})
87
162
  if url == "auto"
88
163
  path = Configuration.temp_path
@@ -93,7 +168,12 @@ module Puma
93
168
  end
94
169
 
95
170
  if opts[:no_token]
96
- auth_token = :none
171
+ # We need to use 'none' rather than :none because this value will be
172
+ # passed on to an instance of OptionParser, which doesn't support
173
+ # symbols as option values.
174
+ #
175
+ # See: https://github.com/puma/puma/issues/1193#issuecomment-305995488
176
+ auth_token = 'none'
97
177
  else
98
178
  auth_token = opts[:auth_token]
99
179
  auth_token ||= Configuration.random_token
@@ -110,22 +190,32 @@ module Puma
110
190
  @options[:config_files] << file
111
191
  end
112
192
 
113
- # Adds a binding for the server to +url+. tcp://, unix://, and ssl:// are the only accepted
114
- # protocols. Use query parameters within the url to specify options.
193
+ # Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
194
+ # accepted protocols. Multiple urls can be bound to, calling `bind` does
195
+ # not overwrite previous bindings.
115
196
  #
116
- # @note multiple urls can be bound to, calling `bind` does not overwrite previous bindings.
197
+ # The default is "tcp://0.0.0.0:9292".
117
198
  #
118
- # @example Explicitly the socket backlog depth (default is 1024)
119
- # bind('unix:///var/run/puma.sock?backlog=2048')
199
+ # You can use query parameters within the url to specify options:
120
200
  #
121
- # @example Set up ssl cert
122
- # bind('ssl://127.0.0.1:9292?key=key.key&cert=cert.pem')
201
+ # * Set the socket backlog depth with +backlog+, default is 1024.
202
+ # * Set up an SSL certificate with +key+ & +cert+.
203
+ # * Set whether to optimize for low latency instead of throughput with
204
+ # +low_latency+, default is to optimize for low latency. This is done
205
+ # via +Socket::TCP_NODELAY+.
206
+ # * Set socket permissions with +umask+.
123
207
  #
124
- # @example Prefer low-latency over higher throughput (via `Socket::TCP_NODELAY`)
125
- # bind('tcp://0.0.0.0:9292?low_latency=true')
208
+ # @example Backlog depth
209
+ # bind 'unix:///var/run/puma.sock?backlog=512'
210
+ # @example SSL cert
211
+ # bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
212
+ # @example Disable optimization for low latency
213
+ # bind 'tcp://0.0.0.0:9292?low_latency=false'
214
+ # @example Socket permissions
215
+ # bind 'unix:///var/run/puma.sock?umask=0111'
216
+ # @see Puma::Runner#load_and_bind
217
+ # @see Puma::Cluster#run
126
218
  #
127
- # @example Set socket permissions
128
- # bind('unix:///var/run/puma.sock?umask=0111')
129
219
  def bind(url)
130
220
  @options[:binds] ||= []
131
221
  @options[:binds] << url
@@ -135,48 +225,75 @@ module Puma
135
225
  @options[:binds] = []
136
226
  end
137
227
 
228
+ # Bind to (systemd) activated sockets, regardless of configured binds.
229
+ #
230
+ # Systemd can present sockets as file descriptors that are already opened.
231
+ # By default Puma will use these but only if it was explicitly told to bind
232
+ # to the socket. If not, it will close the activated sockets. This means
233
+ # all configuration is duplicated.
234
+ #
235
+ # Binds can contain additional configuration, but only SSL config is really
236
+ # relevant since the unix and TCP socket options are ignored.
237
+ #
238
+ # This means there is a lot of duplicated configuration for no additional
239
+ # value in most setups. This method tells the launcher to bind to all
240
+ # activated sockets, regardless of existing bind.
241
+ #
242
+ # To clear configured binds, the value only can be passed. This will clear
243
+ # out any binds that may have been configured.
244
+ #
245
+ # @example Use any systemd activated sockets as well as configured binds
246
+ # bind_to_activated_sockets
247
+ #
248
+ # @example Only bind to systemd activated sockets, ignoring other binds
249
+ # bind_to_activated_sockets 'only'
250
+ def bind_to_activated_sockets(bind=true)
251
+ @options[:bind_to_activated_sockets] = bind
252
+ end
253
+
138
254
  # Define the TCP port to bind to. Use +bind+ for more advanced options.
139
255
  #
256
+ # @example
257
+ # port 9292
140
258
  def port(port, host=nil)
141
- host ||= Configuration::DefaultTCPHost
142
- bind "tcp://#{host}:#{port}"
259
+ host ||= default_host
260
+ bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
143
261
  end
144
262
 
145
- # Define how long persistent connections can be idle before puma closes
146
- # them
147
- #
263
+ # Define how long persistent connections can be idle before Puma closes them.
264
+ # @see Puma::Server.new
148
265
  def persistent_timeout(seconds)
149
266
  @options[:persistent_timeout] = Integer(seconds)
150
267
  end
151
268
 
152
- # Define how long the tcp socket stays open, if no data has been received
153
- #
269
+ # Define how long the tcp socket stays open, if no data has been received.
270
+ # @see Puma::Server.new
154
271
  def first_data_timeout(seconds)
155
272
  @options[:first_data_timeout] = Integer(seconds)
156
273
  end
157
274
 
158
275
  # Work around leaky apps that leave garbage in Thread locals
159
- # across requests
160
- #
276
+ # across requests.
161
277
  def clean_thread_locals(which=true)
162
278
  @options[:clean_thread_locals] = which
163
279
  end
164
280
 
165
- # Daemonize the server into the background. Highly suggest that
166
- # this be combined with +pidfile+ and +stdout_redirect+.
167
- def daemonize(which=true)
168
- @options[:daemon] = which
169
- end
170
-
171
- # When shutting down, drain the accept socket of pending
172
- # connections and process them. This loops over the accept
173
- # socket until there are no more read events and then stops
174
- # looking and waits for the requests to finish.
281
+ # When shutting down, drain the accept socket of pending connections and
282
+ # process them. This loops over the accept socket until there are no more
283
+ # read events and then stops looking and waits for the requests to finish.
284
+ # @see Puma::Server#graceful_shutdown
285
+ #
175
286
  def drain_on_shutdown(which=true)
176
287
  @options[:drain_on_shutdown] = which
177
288
  end
178
289
 
179
- # Set the environment in which the Rack's app will run.
290
+ # Set the environment in which the rack's app will run. The value must be
291
+ # a string.
292
+ #
293
+ # The default is "development".
294
+ #
295
+ # @example
296
+ # environment 'production'
180
297
  def environment(environment)
181
298
  @options[:environment] = environment
182
299
  end
@@ -188,6 +305,7 @@ module Puma
188
305
  #
189
306
  # Puma always waits a few seconds after killing a thread for it to try
190
307
  # to finish up it's work, even in :immediately mode.
308
+ # @see Puma::Server#graceful_shutdown
191
309
  def force_shutdown_after(val=:forever)
192
310
  i = case val
193
311
  when :forever
@@ -195,37 +313,48 @@ module Puma
195
313
  when :immediately
196
314
  0
197
315
  else
198
- Integer(val)
316
+ Float(val)
199
317
  end
200
318
 
201
319
  @options[:force_shutdown_after] = i
202
320
  end
203
321
 
204
322
  # Code to run before doing a restart. This code should
205
- # close logfiles, database connections, etc.
323
+ # close log files, database connections, etc.
206
324
  #
207
325
  # This can be called multiple times to add code each time.
208
326
  #
327
+ # @example
328
+ # on_restart do
329
+ # puts 'On restart...'
330
+ # end
209
331
  def on_restart(&block)
210
332
  @options[:on_restart] ||= []
211
333
  @options[:on_restart] << block
212
334
  end
213
335
 
214
- # Command to use to restart puma. This should be just how to
215
- # load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
216
- # to puma, as those are the same as the original process.
336
+ # Command to use to restart Puma. This should be just how to
337
+ # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
338
+ # to Puma, as those are the same as the original process.
217
339
  #
340
+ # @example
341
+ # restart_command '/u/app/lolcat/bin/restart_puma'
218
342
  def restart_command(cmd)
219
343
  @options[:restart_cmd] = cmd.to_s
220
344
  end
221
345
 
222
- # Store the pid of the server in the file at +path+.
346
+ # Store the pid of the server in the file at "path".
347
+ #
348
+ # @example
349
+ # pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
223
350
  def pidfile(path)
224
351
  @options[:pidfile] = path.to_s
225
352
  end
226
353
 
227
- # Disable request logging.
354
+ # Disable request logging, if this isn't used it'll be enabled by default.
228
355
  #
356
+ # @example
357
+ # quiet
229
358
  def quiet(which=true)
230
359
  @options[:log_requests] = !which
231
360
  end
@@ -244,30 +373,47 @@ module Puma
244
373
 
245
374
  # Load +path+ as a rackup file.
246
375
  #
247
- def rackup(path)
248
- @options[:rackup] = path.to_s
249
- end
250
-
251
- # Run Puma in TCP mode
376
+ # The default is "config.ru".
252
377
  #
253
- def tcp_mode!
254
- @options[:mode] = :tcp
378
+ # @example
379
+ # rackup '/u/apps/lolcat/config.ru'
380
+ def rackup(path)
381
+ @options[:rackup] ||= path.to_s
255
382
  end
256
383
 
257
384
  def early_hints(answer=true)
258
385
  @options[:early_hints] = answer
259
386
  end
260
387
 
261
- # Redirect STDOUT and STDERR to files specified.
388
+ # Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
389
+ # specifies whether the output is appended, the default is +false+.
390
+ #
391
+ # @example
392
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
393
+ # @example
394
+ # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
262
395
  def stdout_redirect(stdout=nil, stderr=nil, append=false)
263
396
  @options[:redirect_stdout] = stdout
264
397
  @options[:redirect_stderr] = stderr
265
398
  @options[:redirect_append] = append
266
399
  end
267
400
 
401
+ def log_formatter(&block)
402
+ @options[:log_formatter] = block
403
+ end
404
+
268
405
  # Configure +min+ to be the minimum number of threads to use to answer
269
406
  # requests and +max+ the maximum.
270
407
  #
408
+ # The default is the environment variables +PUMA_MIN_THREADS+ / +PUMA_MAX_THREADS+
409
+ # (or +MIN_THREADS+ / +MAX_THREADS+ if the +PUMA_+ variables aren't set).
410
+ #
411
+ # If these environment variables aren't set, the default is "0, 5" in MRI or "0, 16" for other interpreters.
412
+ #
413
+ # @example
414
+ # threads 0, 16
415
+ # @example
416
+ # threads 5, 5
271
417
  def threads(min, max)
272
418
  min = Integer(min)
273
419
  max = Integer(max)
@@ -283,81 +429,153 @@ module Puma
283
429
  @options[:max_threads] = max
284
430
  end
285
431
 
432
+ # Instead of `bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'` you
433
+ # can also use the this method.
434
+ #
435
+ # @example
436
+ # ssl_bind '127.0.0.1', '9292', {
437
+ # cert: path_to_cert,
438
+ # key: path_to_key,
439
+ # ssl_cipher_filter: cipher_filter, # optional
440
+ # verify_mode: verify_mode, # default 'none'
441
+ # verification_flags: flags, # optional, not supported by JRuby
442
+ # }
443
+ # @example For JRuby, two keys are required: keystore & keystore_pass.
444
+ # ssl_bind '127.0.0.1', '9292', {
445
+ # keystore: path_to_keystore,
446
+ # keystore_pass: password,
447
+ # ssl_cipher_list: cipher_list, # optional
448
+ # verify_mode: verify_mode # default 'none'
449
+ # }
286
450
  def ssl_bind(host, port, opts)
287
- verify = opts.fetch(:verify_mode, 'none')
288
-
289
- if defined?(JRUBY_VERSION)
290
- keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
291
- bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}"
292
- else
293
- bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&verify_mode=#{verify}"
294
- end
451
+ bind self.class.ssl_bind_str(host, port, opts)
295
452
  end
296
453
 
297
454
  # Use +path+ as the file to store the server info state. This is
298
- # used by pumactl to query and control the server.
455
+ # used by +pumactl+ to query and control the server.
299
456
  #
457
+ # @example
458
+ # state_path '/u/apps/lolcat/tmp/pids/puma.state'
300
459
  def state_path(path)
301
460
  @options[:state] = path.to_s
302
461
  end
303
462
 
304
- # *Cluster mode only* How many worker processes to run.
463
+ # Use +permission+ to restrict permissions for the state file.
464
+ #
465
+ # @example
466
+ # state_permission 0600
467
+ # @version 5.0.0
305
468
  #
469
+ def state_permission(permission)
470
+ @options[:state_permission] = permission
471
+ end
472
+
473
+ # How many worker processes to run. Typically this is set to
474
+ # the number of available cores.
475
+ #
476
+ # The default is the value of the environment variable +WEB_CONCURRENCY+ if
477
+ # set, otherwise 0.
478
+ #
479
+ # @note Cluster mode only.
480
+ # @see Puma::Cluster
306
481
  def workers(count)
307
482
  @options[:workers] = count.to_i
308
483
  end
309
484
 
310
- # *Cluster mode only* Code to run immediately before master process
485
+ # Disable warning message when running in cluster mode with a single worker.
486
+ #
487
+ # Cluster mode has some overhead of running an additional 'control' process
488
+ # in order to manage the cluster. If only running a single worker it is
489
+ # likely not worth paying that overhead vs running in single mode with
490
+ # additional threads instead.
491
+ #
492
+ # There are some scenarios where running cluster mode with a single worker
493
+ # may still be warranted and valid under certain deployment scenarios, see
494
+ # https://github.com/puma/puma/issues/2534
495
+ #
496
+ # Moving from workers = 1 to workers = 0 will save 10-30% of memory use.
497
+ #
498
+ # @note Cluster mode only.
499
+ def silence_single_worker_warning
500
+ @options[:silence_single_worker_warning] = true
501
+ end
502
+
503
+ # Code to run immediately before master process
311
504
  # forks workers (once on boot). These hooks can block if necessary
312
- # to wait for background operations unknown to puma to finish before
505
+ # to wait for background operations unknown to Puma to finish before
313
506
  # the process terminates.
314
- # This can be used to close any connections to remote servers (database, redis, ...)
315
- # that were opened when preloading the code
507
+ # This can be used to close any connections to remote servers (database,
508
+ # Redis, ...) that were opened when preloading the code.
316
509
  #
317
- # This can be called multiple times to add hooks.
510
+ # This can be called multiple times to add several hooks.
318
511
  #
512
+ # @note Cluster mode only.
513
+ # @example
514
+ # before_fork do
515
+ # puts "Starting workers..."
516
+ # end
319
517
  def before_fork(&block)
320
518
  @options[:before_fork] ||= []
321
519
  @options[:before_fork] << block
322
520
  end
323
521
 
324
- # *Cluster mode only* Code to run in a worker when it boots to setup
522
+ # Code to run in a worker when it boots to setup
325
523
  # the process before booting the app.
326
524
  #
327
- # This can be called multiple times to add hooks.
525
+ # This can be called multiple times to add several hooks.
328
526
  #
527
+ # @note Cluster mode only.
528
+ # @example
529
+ # on_worker_boot do
530
+ # puts 'Before worker boot...'
531
+ # end
329
532
  def on_worker_boot(&block)
330
533
  @options[:before_worker_boot] ||= []
331
534
  @options[:before_worker_boot] << block
332
535
  end
333
536
 
334
- # *Cluster mode only* Code to run immediately before a worker shuts
537
+ # Code to run immediately before a worker shuts
335
538
  # down (after it has finished processing HTTP requests). These hooks
336
539
  # can block if necessary to wait for background operations unknown
337
- # to puma to finish before the process terminates.
540
+ # to Puma to finish before the process terminates.
338
541
  #
339
- # This can be called multiple times to add hooks.
542
+ # This can be called multiple times to add several hooks.
340
543
  #
544
+ # @note Cluster mode only.
545
+ # @example
546
+ # on_worker_shutdown do
547
+ # puts 'On worker shutdown...'
548
+ # end
341
549
  def on_worker_shutdown(&block)
342
550
  @options[:before_worker_shutdown] ||= []
343
551
  @options[:before_worker_shutdown] << block
344
552
  end
345
553
 
346
- # *Cluster mode only* Code to run in the master when it is
347
- # about to create the worker by forking itself.
554
+ # Code to run in the master right before a worker is started. The worker's
555
+ # index is passed as an argument.
348
556
  #
349
- # This can be called multiple times to add hooks.
557
+ # This can be called multiple times to add several hooks.
350
558
  #
559
+ # @note Cluster mode only.
560
+ # @example
561
+ # on_worker_fork do
562
+ # puts 'Before worker fork...'
563
+ # end
351
564
  def on_worker_fork(&block)
352
565
  @options[:before_worker_fork] ||= []
353
566
  @options[:before_worker_fork] << block
354
567
  end
355
568
 
356
- # *Cluster mode only* Code to run in the master after it starts
357
- # a worker.
569
+ # Code to run in the master after a worker has been started. The worker's
570
+ # index is passed as an argument.
358
571
  #
359
- # This can be called multiple times to add hooks.
572
+ # This is called everytime a worker is to be started.
360
573
  #
574
+ # @note Cluster mode only.
575
+ # @example
576
+ # after_worker_fork do
577
+ # puts 'After worker fork...'
578
+ # end
361
579
  def after_worker_fork(&block)
362
580
  @options[:after_worker_fork] ||= []
363
581
  @options[:after_worker_fork] = block
@@ -365,33 +583,70 @@ module Puma
365
583
 
366
584
  alias_method :after_worker_boot, :after_worker_fork
367
585
 
368
- # The directory to operate out of.
369
- def directory(dir)
370
- @options[:directory] = dir.to_s
586
+ # When `fork_worker` is enabled, code to run in Worker 0
587
+ # before all other workers are re-forked from this process,
588
+ # after the server has temporarily stopped serving requests
589
+ # (once per complete refork cycle).
590
+ #
591
+ # This can be used to trigger extra garbage-collection to maximize
592
+ # copy-on-write efficiency, or close any connections to remote servers
593
+ # (database, Redis, ...) that were opened while the server was running.
594
+ #
595
+ # This can be called multiple times to add several hooks.
596
+ #
597
+ # @note Cluster mode with `fork_worker` enabled only.
598
+ # @example
599
+ # on_refork do
600
+ # 3.times {GC.start}
601
+ # end
602
+ # @version 5.0.0
603
+ #
604
+ def on_refork(&block)
605
+ @options[:before_refork] ||= []
606
+ @options[:before_refork] << block
371
607
  end
372
608
 
373
- # DEPRECATED: The directory to operate out of.
374
- def worker_directory(dir)
375
- $stderr.puts "worker_directory is deprecated. Please use `directory`"
376
- directory dir
609
+ # Code to run out-of-band when the worker is idle.
610
+ # These hooks run immediately after a request has finished
611
+ # processing and there are no busy threads on the worker.
612
+ # The worker doesn't accept new requests until this code finishes.
613
+ #
614
+ # This hook is useful for running out-of-band garbage collection
615
+ # or scheduling asynchronous tasks to execute after a response.
616
+ #
617
+ # This can be called multiple times to add several hooks.
618
+ def out_of_band(&block)
619
+ @options[:out_of_band] ||= []
620
+ @options[:out_of_band] << block
377
621
  end
378
622
 
379
- # Run the app as a raw TCP app instead of an HTTP rack app
380
- def tcp_mode
381
- @options[:mode] = :tcp
623
+ # The directory to operate out of.
624
+ #
625
+ # The default is the current directory.
626
+ #
627
+ # @example
628
+ # directory '/u/apps/lolcat'
629
+ def directory(dir)
630
+ @options[:directory] = dir.to_s
382
631
  end
383
632
 
384
- # *Cluster mode only* Preload the application before starting
385
- # the workers and setting up the listen ports. This conflicts
386
- # with using the phased restart feature, you can't use both.
633
+ # Preload the application before starting the workers; this conflicts with
634
+ # phased restart feature. On by default if your app uses more than 1 worker.
387
635
  #
636
+ # @note Cluster mode only.
637
+ # @example
638
+ # preload_app!
388
639
  def preload_app!(answer=true)
389
640
  @options[:preload_app] = answer
390
641
  end
391
642
 
392
- # Use +obj+ or +block+ as the low level error handler. This allows a config file to
393
- # change the default error on the server.
643
+ # Use +obj+ or +block+ as the low level error handler. This allows the
644
+ # configuration file to change the default error on the server.
394
645
  #
646
+ # @example
647
+ # lowlevel_error_handler do |err|
648
+ # [200, {}, ["error page"]]
649
+ # end
395
650
  def lowlevel_error_handler(obj=nil, &block)
396
651
  obj ||= block
397
652
  raise "Provide either a #call'able or a block" unless obj
@@ -401,38 +656,112 @@ module Puma
401
656
  # This option is used to allow your app and its gems to be
402
657
  # properly reloaded when not using preload.
403
658
  #
404
- # When set, if puma detects that it's been invoked in the
659
+ # When set, if Puma detects that it's been invoked in the
405
660
  # context of Bundler, it will cleanup the environment and
406
661
  # re-run itself outside the Bundler environment, but directly
407
662
  # using the files that Bundler has setup.
408
663
  #
409
- # This means that puma is now decoupled from your Bundler
664
+ # This means that Puma is now decoupled from your Bundler
410
665
  # context and when each worker loads, it will be loading a
411
666
  # new Bundler context and thus can float around as the release
412
667
  # dictates.
668
+ #
669
+ # @see extra_runtime_dependencies
670
+ #
671
+ # @note This is incompatible with +preload_app!+.
672
+ # @note This is only supported for RubyGems 2.2+
413
673
  def prune_bundler(answer=true)
414
674
  @options[:prune_bundler] = answer
415
675
  end
416
676
 
417
- # Additional text to display in process listing
677
+ # By default, Puma will raise SignalException when SIGTERM is received. In
678
+ # environments where SIGTERM is something expected, you can suppress these
679
+ # with this option.
680
+ #
681
+ # This can be useful for example in Kubernetes, where rolling restart is
682
+ # guaranteed usually on infrastructure level.
683
+ #
684
+ # @example
685
+ # raise_exception_on_sigterm false
686
+ # @see Puma::Launcher#setup_signals
687
+ # @see Puma::Cluster#setup_signals
688
+ #
689
+ def raise_exception_on_sigterm(answer=true)
690
+ @options[:raise_exception_on_sigterm] = answer
691
+ end
692
+
693
+ # When using prune_bundler, if extra runtime dependencies need to be loaded to
694
+ # initialize your app, then this setting can be used. This includes any Puma plugins.
695
+ #
696
+ # Before bundler is pruned, the gem names supplied will be looked up in the bundler
697
+ # context and then loaded again after bundler is pruned.
698
+ # Only applies if prune_bundler is used.
699
+ #
700
+ # @example
701
+ # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
702
+ # @example
703
+ # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
704
+ # @see Puma::Launcher#extra_runtime_deps_directories
705
+ #
706
+ def extra_runtime_dependencies(answer = [])
707
+ @options[:extra_runtime_dependencies] = Array(answer)
708
+ end
709
+
710
+ # Additional text to display in process listing.
711
+ #
712
+ # If you do not specify a tag, Puma will infer it. If you do not want Puma
713
+ # to add a tag, use an empty string.
714
+ #
715
+ # @example
716
+ # tag 'app name'
717
+ # @example
718
+ # tag ''
418
719
  def tag(string)
419
720
  @options[:tag] = string.to_s
420
721
  end
421
722
 
422
- # *Cluster mode only* Set the timeout for workers in seconds
423
- # When set the master process will terminate any workers
424
- # that have not checked in within the given +timeout+.
425
- # This mitigates hung processes. Default value is 60 seconds.
723
+ # Verifies that all workers have checked in to the master process within
724
+ # the given timeout. If not the worker process will be restarted. This is
725
+ # not a request timeout, it is to protect against a hung or dead process.
726
+ # Setting this value will not protect against slow requests.
727
+ #
728
+ # The minimum value is 6 seconds, the default value is 60 seconds.
729
+ #
730
+ # @note Cluster mode only.
731
+ # @example
732
+ # worker_timeout 60
733
+ # @see Puma::Cluster::Worker#ping_timeout
734
+ #
426
735
  def worker_timeout(timeout)
427
- @options[:worker_timeout] = Integer(timeout)
736
+ timeout = Integer(timeout)
737
+ min = Const::WORKER_CHECK_INTERVAL
738
+
739
+ if timeout <= min
740
+ raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
741
+ end
742
+
743
+ @options[:worker_timeout] = timeout
428
744
  end
429
745
 
430
- # *Cluster mode only* Set the timeout for workers to boot
746
+ # Change the default worker timeout for booting.
747
+ #
748
+ # If unspecified, this defaults to the value of worker_timeout.
749
+ #
750
+ # @note Cluster mode only.
751
+ #
752
+ # @example
753
+ # worker_boot_timeout 60
754
+ # @see Puma::Cluster::Worker#ping_timeout
755
+ #
431
756
  def worker_boot_timeout(timeout)
432
757
  @options[:worker_boot_timeout] = Integer(timeout)
433
758
  end
434
759
 
435
- # *Cluster mode only* Set the timeout for worker shutdown
760
+ # Set the timeout for worker shutdown.
761
+ #
762
+ # @note Cluster mode only.
763
+ # @see Puma::Cluster::Worker#term
764
+ #
436
765
  def worker_shutdown_timeout(timeout)
437
766
  @options[:worker_shutdown_timeout] = Integer(timeout)
438
767
  end
@@ -449,7 +778,8 @@ module Puma
449
778
  # Note that setting this to false disables HTTP keepalive and
450
779
  # slow clients will occupy a handler thread while the request
451
780
  # is being sent. A reverse proxy, such as nginx, can handle
452
- # slow clients and queue requests before they reach puma.
781
+ # slow clients and queue requests before they reach Puma.
782
+ # @see Puma::Server
453
783
  def queue_requests(answer=true)
454
784
  @options[:queue_requests] = answer
455
785
  end
@@ -457,10 +787,25 @@ module Puma
457
787
  # When a shutdown is requested, the backtraces of all the
458
788
  # threads will be written to $stdout. This can help figure
459
789
  # out why shutdown is hanging.
790
+ #
460
791
  def shutdown_debug(val=true)
461
792
  @options[:shutdown_debug] = val
462
793
  end
463
794
 
795
+
796
+ # Attempts to route traffic to less-busy workers by causing them to delay
797
+ # listening on the socket, allowing workers which are not processing any
798
+ # requests to pick up new requests first.
799
+ #
800
+ # Only works on MRI. For all other interpreters, this setting does nothing.
801
+ # @see Puma::Server#handle_servers
802
+ # @see Puma::ThreadPool#wait_for_less_busy_worker
803
+ # @version 5.0.0
804
+ #
805
+ def wait_for_less_busy_worker(val=0.005)
806
+ @options[:wait_for_less_busy_worker] = val.to_f
807
+ end
808
+
464
809
  # Control how the remote address of the connection is set. This
465
810
  # is configurable because to calculate the true socket peer address
466
811
  # a kernel syscall is required which for very fast rack handlers
@@ -468,18 +813,18 @@ module Puma
468
813
  #
469
814
  # There are 4 possible values:
470
815
  #
471
- # * :socket (the default) - read the peername from the socket using the
472
- # syscall. This is the normal behavior.
473
- # * :localhost - set the remote address to "127.0.0.1"
474
- # * header: http_header - set the remote address to the value of the
475
- # provided http header. For instance:
476
- # `set_remote_address header: "X-Real-IP"`.
477
- # Only the first word (as separated by spaces or comma)
478
- # is used, allowing headers such as X-Forwarded-For
479
- # to be used as well.
480
- # * Any string - this allows you to hardcode remote address to any value
481
- # you wish. Because puma never uses this field anyway, it's
482
- # format is entirely in your hands.
816
+ # 1. **:socket** (the default) - read the peername from the socket using the
817
+ # syscall. This is the normal behavior.
818
+ # 2. **:localhost** - set the remote address to "127.0.0.1"
819
+ # 3. **header: <http_header>**- set the remote address to the value of the
820
+ # provided http header. For instance:
821
+ # `set_remote_address header: "X-Real-IP"`.
822
+ # Only the first word (as separated by spaces or comma) is used, allowing
823
+ # headers such as X-Forwarded-For to be used as well.
824
+ # 4. **\<Any string\>** - this allows you to hardcode remote address to any value
825
+ # you wish. Because Puma never uses this field anyway, it's format is
826
+ # entirely in your hands.
827
+ #
483
828
  def set_remote_address(val=:socket)
484
829
  case val
485
830
  when :socket
@@ -493,7 +838,7 @@ module Puma
493
838
  when Hash
494
839
  if hdr = val[:header]
495
840
  @options[:remote_address] = :header
496
- @options[:remote_address_header] = "HTTP_" + hdr.upcase.gsub("-", "_")
841
+ @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
497
842
  else
498
843
  raise "Invalid value for set_remote_address - #{val.inspect}"
499
844
  end
@@ -502,5 +847,68 @@ module Puma
502
847
  end
503
848
  end
504
849
 
850
+ # When enabled, workers will be forked from worker 0 instead of from the master process.
851
+ # This option is similar to `preload_app` because the app is preloaded before forking,
852
+ # but it is compatible with phased restart.
853
+ #
854
+ # This option also enables the `refork` command (SIGURG), which optimizes copy-on-write performance
855
+ # in a running app.
856
+ #
857
+ # A refork will automatically trigger once after the specified number of requests
858
+ # (default 1000), or pass 0 to disable auto refork.
859
+ #
860
+ # @note Cluster mode only.
861
+ # @version 5.0.0
862
+ #
863
+ def fork_worker(after_requests=1000)
864
+ @options[:fork_worker] = Integer(after_requests)
865
+ end
866
+
867
+ # When enabled, Puma will GC 4 times before forking workers.
868
+ # If available (Ruby 2.7+), we will also call GC.compact.
869
+ # Not recommended for non-MRI Rubies.
870
+ #
871
+ # Based on the work of Koichi Sasada and Aaron Patterson, this option may
872
+ # decrease memory utilization of preload-enabled cluster-mode Pumas. It will
873
+ # also increase time to boot and fork. See your logs for details on how much
874
+ # time this adds to your boot process. For most apps, it will be less than one
875
+ # second.
876
+ #
877
+ # @see Puma::Cluster#nakayoshi_gc
878
+ # @version 5.0.0
879
+ #
880
+ def nakayoshi_fork(enabled=true)
881
+ @options[:nakayoshi_fork] = enabled
882
+ end
883
+
884
+ # The number of requests to attempt inline before sending a client back to
885
+ # the reactor to be subject to normal ordering.
886
+ #
887
+ def max_fast_inline(num_of_requests)
888
+ @options[:max_fast_inline] = Float(num_of_requests)
889
+ end
890
+
891
+ # Specify the backend for the IO selector.
892
+ #
893
+ # Provided values will be passed directly to +NIO::Selector.new+, with the
894
+ # exception of +:auto+ which will let nio4r choose the backend.
895
+ #
896
+ # Check the documentation of +NIO::Selector.backends+ for the list of valid
897
+ # options. Note that the available options on your system will depend on the
898
+ # operating system. If you want to use the pure Ruby backend (not
899
+ # recommended due to its comparatively low performance), set environment
900
+ # variable +NIO4R_PURE+ to +true+.
901
+ #
902
+ # The default is +:auto+.
903
+ #
904
+ # @see https://github.com/socketry/nio4r/blob/master/lib/nio/selector.rb
905
+ #
906
+ def io_selector_backend(backend)
907
+ @options[:io_selector_backend] = backend.to_sym
908
+ end
909
+
910
+ def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
911
+ @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
912
+ end
505
913
  end
506
914
  end