puma 4.3.12 → 5.6.6

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 +1511 -524
  3. data/LICENSE +23 -20
  4. data/README.md +120 -36
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +63 -26
  7. data/docs/compile_options.md +21 -0
  8. data/docs/deployment.md +60 -69
  9. data/docs/fork_worker.md +33 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +9 -0
  14. data/{tools → docs}/jungle/rc.d/README.md +1 -1
  15. data/{tools → docs}/jungle/rc.d/puma +2 -2
  16. data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
  17. data/docs/kubernetes.md +66 -0
  18. data/docs/nginx.md +1 -1
  19. data/docs/plugins.md +15 -15
  20. data/docs/rails_dev_mode.md +28 -0
  21. data/docs/restart.md +46 -23
  22. data/docs/signals.md +13 -11
  23. data/docs/stats.md +142 -0
  24. data/docs/systemd.md +85 -128
  25. data/ext/puma_http11/PumaHttp11Service.java +2 -4
  26. data/ext/puma_http11/ext_help.h +1 -1
  27. data/ext/puma_http11/extconf.rb +44 -10
  28. data/ext/puma_http11/http11_parser.c +45 -47
  29. data/ext/puma_http11/http11_parser.h +1 -1
  30. data/ext/puma_http11/http11_parser.java.rl +1 -1
  31. data/ext/puma_http11/http11_parser.rl +1 -1
  32. data/ext/puma_http11/http11_parser_common.rl +0 -0
  33. data/ext/puma_http11/mini_ssl.c +225 -89
  34. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  35. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  36. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +3 -5
  37. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +109 -67
  38. data/ext/puma_http11/puma_http11.c +32 -51
  39. data/lib/puma/app/status.rb +50 -36
  40. data/lib/puma/binder.rb +225 -106
  41. data/lib/puma/cli.rb +24 -18
  42. data/lib/puma/client.rb +104 -76
  43. data/lib/puma/cluster/worker.rb +173 -0
  44. data/lib/puma/cluster/worker_handle.rb +94 -0
  45. data/lib/puma/cluster.rb +212 -220
  46. data/lib/puma/commonlogger.rb +2 -2
  47. data/lib/puma/configuration.rb +58 -49
  48. data/lib/puma/const.rb +13 -6
  49. data/lib/puma/control_cli.rb +99 -76
  50. data/lib/puma/detect.rb +29 -2
  51. data/lib/puma/dsl.rb +368 -96
  52. data/lib/puma/error_logger.rb +104 -0
  53. data/lib/puma/events.rb +55 -34
  54. data/lib/puma/io_buffer.rb +9 -2
  55. data/lib/puma/jruby_restart.rb +0 -58
  56. data/lib/puma/json_serialization.rb +96 -0
  57. data/lib/puma/launcher.rb +128 -46
  58. data/lib/puma/minissl/context_builder.rb +14 -9
  59. data/lib/puma/minissl.rb +137 -50
  60. data/lib/puma/null_io.rb +18 -1
  61. data/lib/puma/plugin/tmp_restart.rb +0 -0
  62. data/lib/puma/plugin.rb +3 -12
  63. data/lib/puma/queue_close.rb +26 -0
  64. data/lib/puma/rack/builder.rb +1 -5
  65. data/lib/puma/rack/urlmap.rb +0 -0
  66. data/lib/puma/rack_default.rb +0 -0
  67. data/lib/puma/reactor.rb +85 -369
  68. data/lib/puma/request.rb +476 -0
  69. data/lib/puma/runner.rb +46 -61
  70. data/lib/puma/server.rb +292 -763
  71. data/lib/puma/single.rb +9 -65
  72. data/lib/puma/state_file.rb +48 -8
  73. data/lib/puma/systemd.rb +46 -0
  74. data/lib/puma/thread_pool.rb +125 -57
  75. data/lib/puma/util.rb +32 -4
  76. data/lib/puma.rb +48 -0
  77. data/lib/rack/handler/puma.rb +2 -3
  78. data/lib/rack/version_restriction.rb +15 -0
  79. data/tools/{docker/Dockerfile → Dockerfile} +1 -1
  80. data/tools/trickletest.rb +0 -0
  81. metadata +28 -23
  82. data/docs/tcp_mode.md +0 -96
  83. data/ext/puma_http11/io_buffer.c +0 -155
  84. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
  85. data/lib/puma/accept_nonblock.rb +0 -29
  86. data/lib/puma/tcp_logger.rb +0 -41
  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,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'puma/const'
4
+ require 'puma/util'
4
5
 
5
6
  module Puma
6
7
  # The methods that are available for use inside the configuration file.
@@ -14,25 +15,65 @@ module Puma
14
15
  # end
15
16
  # config.load
16
17
  #
17
- # puts config.options[:binds]
18
- # "tcp://127.0.0.1:3001"
18
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3001"
19
19
  #
20
20
  # Used to load file:
21
21
  #
22
22
  # $ cat puma_config.rb
23
- # port 3002
23
+ # port 3002
24
+ #
25
+ # Resulting configuration:
24
26
  #
25
27
  # config = Configuration.new(config_file: "puma_config.rb")
26
28
  # config.load
27
29
  #
28
- # puts config.options[:binds]
29
- # # => "tcp://127.0.0.1:3002"
30
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3002"
30
31
  #
31
32
  # You can also find many examples being used by the test suite in
32
33
  # +test/config+.
34
+ #
33
35
  class DSL
34
36
  include ConfigDefault
35
37
 
38
+ # convenience method so logic can be used in CI
39
+ # @see ssl_bind
40
+ #
41
+ def self.ssl_bind_str(host, port, opts)
42
+ verify = opts.fetch(:verify_mode, 'none').to_s
43
+
44
+ tls_str =
45
+ if opts[:no_tlsv1_1] then '&no_tlsv1_1=true'
46
+ elsif opts[:no_tlsv1] then '&no_tlsv1=true'
47
+ else ''
48
+ end
49
+
50
+ ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
51
+
52
+ backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
53
+
54
+ if defined?(JRUBY_VERSION)
55
+ ssl_cipher_list = opts[:ssl_cipher_list] ?
56
+ "&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
57
+
58
+ keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
59
+
60
+ "ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
61
+ "&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
62
+ else
63
+ ssl_cipher_filter = opts[:ssl_cipher_filter] ?
64
+ "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
65
+
66
+ v_flags = (ary = opts[:verification_flags]) ?
67
+ "&verification_flags=#{Array(ary).join ','}" : nil
68
+
69
+ cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(opts[:cert])}" : nil
70
+ key_flags = (cert = opts[:key]) ? "&key=#{Puma::Util.escape(opts[:key])}" : nil
71
+
72
+ "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}" \
73
+ "#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
74
+ end
75
+ end
76
+
36
77
  def initialize(options, config)
37
78
  @config = config
38
79
  @options = options
@@ -98,6 +139,9 @@ module Puma
98
139
  # [body]
99
140
  # ]
100
141
  # end
142
+ #
143
+ # @see Puma::Configuration#app
144
+ #
101
145
  def app(obj=nil, &block)
102
146
  obj ||= block
103
147
 
@@ -153,19 +197,19 @@ module Puma
153
197
  end
154
198
 
155
199
  # Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
156
- # accepted protocols. Multiple urls can be bound to, calling `bind` does
200
+ # accepted protocols. Multiple urls can be bound to, calling +bind+ does
157
201
  # not overwrite previous bindings.
158
202
  #
159
203
  # The default is "tcp://0.0.0.0:9292".
160
204
  #
161
205
  # You can use query parameters within the url to specify options:
162
206
  #
163
- # - Set the socket backlog depth with +backlog+, default is 1024.
164
- # - Set up an SSL certificate with +key+ & +cert+.
165
- # - Set whether to optimize for low latency instead of throughput with
166
- # +low_latency+, default is to optimize for low latency. This is done
167
- # via +Socket::TCP_NODELAY+.
168
- # - Set socket permissions with +umask+.
207
+ # * Set the socket backlog depth with +backlog+, default is 1024.
208
+ # * Set up an SSL certificate with +key+ & +cert+.
209
+ # * Set whether to optimize for low latency instead of throughput with
210
+ # +low_latency+, default is to not optimize for low latency. This is done
211
+ # via +Socket::TCP_NODELAY+.
212
+ # * Set socket permissions with +umask+.
169
213
  #
170
214
  # @example Backlog depth
171
215
  # bind 'unix:///var/run/puma.sock?backlog=512'
@@ -175,6 +219,9 @@ module Puma
175
219
  # bind 'tcp://0.0.0.0:9292?low_latency=false'
176
220
  # @example Socket permissions
177
221
  # bind 'unix:///var/run/puma.sock?umask=0111'
222
+ # @see Puma::Runner#load_and_bind
223
+ # @see Puma::Cluster#run
224
+ #
178
225
  def bind(url)
179
226
  @options[:binds] ||= []
180
227
  @options[:binds] << url
@@ -184,22 +231,49 @@ module Puma
184
231
  @options[:binds] = []
185
232
  end
186
233
 
234
+ # Bind to (systemd) activated sockets, regardless of configured binds.
235
+ #
236
+ # Systemd can present sockets as file descriptors that are already opened.
237
+ # By default Puma will use these but only if it was explicitly told to bind
238
+ # to the socket. If not, it will close the activated sockets. This means
239
+ # all configuration is duplicated.
240
+ #
241
+ # Binds can contain additional configuration, but only SSL config is really
242
+ # relevant since the unix and TCP socket options are ignored.
243
+ #
244
+ # This means there is a lot of duplicated configuration for no additional
245
+ # value in most setups. This method tells the launcher to bind to all
246
+ # activated sockets, regardless of existing bind.
247
+ #
248
+ # To clear configured binds, the value only can be passed. This will clear
249
+ # out any binds that may have been configured.
250
+ #
251
+ # @example Use any systemd activated sockets as well as configured binds
252
+ # bind_to_activated_sockets
253
+ #
254
+ # @example Only bind to systemd activated sockets, ignoring other binds
255
+ # bind_to_activated_sockets 'only'
256
+ def bind_to_activated_sockets(bind=true)
257
+ @options[:bind_to_activated_sockets] = bind
258
+ end
259
+
187
260
  # Define the TCP port to bind to. Use +bind+ for more advanced options.
188
261
  #
189
262
  # @example
190
263
  # port 9292
191
264
  def port(port, host=nil)
192
265
  host ||= default_host
193
- bind "tcp://#{host}:#{port}"
266
+ bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
194
267
  end
195
268
 
196
- # Define how long persistent connections can be idle before Puma closes
197
- # them.
269
+ # Define how long persistent connections can be idle before Puma closes them.
270
+ # @see Puma::Server.new
198
271
  def persistent_timeout(seconds)
199
272
  @options[:persistent_timeout] = Integer(seconds)
200
273
  end
201
274
 
202
275
  # Define how long the tcp socket stays open, if no data has been received.
276
+ # @see Puma::Server.new
203
277
  def first_data_timeout(seconds)
204
278
  @options[:first_data_timeout] = Integer(seconds)
205
279
  end
@@ -210,24 +284,11 @@ module Puma
210
284
  @options[:clean_thread_locals] = which
211
285
  end
212
286
 
213
- # Daemonize the server into the background. It's highly recommended to
214
- # use this in combination with +pidfile+ and +stdout_redirect+.
287
+ # When shutting down, drain the accept socket of pending connections and
288
+ # process them. This loops over the accept socket until there are no more
289
+ # read events and then stops looking and waits for the requests to finish.
290
+ # @see Puma::Server#graceful_shutdown
215
291
  #
216
- # The default is "false".
217
- #
218
- # @example
219
- # daemonize
220
- #
221
- # @example
222
- # daemonize false
223
- def daemonize(which=true)
224
- @options[:daemon] = which
225
- end
226
-
227
- # When shutting down, drain the accept socket of pending
228
- # connections and process them. This loops over the accept
229
- # socket until there are no more read events and then stops
230
- # looking and waits for the requests to finish.
231
292
  def drain_on_shutdown(which=true)
232
293
  @options[:drain_on_shutdown] = which
233
294
  end
@@ -250,6 +311,7 @@ module Puma
250
311
  #
251
312
  # Puma always waits a few seconds after killing a thread for it to try
252
313
  # to finish up it's work, even in :immediately mode.
314
+ # @see Puma::Server#graceful_shutdown
253
315
  def force_shutdown_after(val=:forever)
254
316
  i = case val
255
317
  when :forever
@@ -257,7 +319,7 @@ module Puma
257
319
  when :immediately
258
320
  0
259
321
  else
260
- Integer(val)
322
+ Float(val)
261
323
  end
262
324
 
263
325
  @options[:force_shutdown_after] = i
@@ -322,20 +384,21 @@ module Puma
322
384
  # @example
323
385
  # rackup '/u/apps/lolcat/config.ru'
324
386
  def rackup(path)
325
- @options[:rackup] = path.to_s
387
+ @options[:rackup] ||= path.to_s
326
388
  end
327
389
 
328
- # Run Puma in TCP mode
329
- #
330
- def tcp_mode!
331
- @options[:mode] = :tcp
390
+ # Allows setting `env['rack.url_scheme']`.
391
+ # Only necessary if X-Forwarded-Proto is not being set by your proxy
392
+ # Normal values are 'http' or 'https'.
393
+ def rack_url_scheme(scheme=nil)
394
+ @options[:rack_url_scheme] = scheme
332
395
  end
333
396
 
334
397
  def early_hints(answer=true)
335
398
  @options[:early_hints] = answer
336
399
  end
337
400
 
338
- # Redirect STDOUT and STDERR to files specified. The +append+ parameter
401
+ # Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
339
402
  # specifies whether the output is appended, the default is +false+.
340
403
  #
341
404
  # @example
@@ -355,7 +418,10 @@ module Puma
355
418
  # Configure +min+ to be the minimum number of threads to use to answer
356
419
  # requests and +max+ the maximum.
357
420
  #
358
- # The default is "0, 16".
421
+ # The default is the environment variables +PUMA_MIN_THREADS+ / +PUMA_MAX_THREADS+
422
+ # (or +MIN_THREADS+ / +MAX_THREADS+ if the +PUMA_+ variables aren't set).
423
+ #
424
+ # If these environment variables aren't set, the default is "0, 5" in MRI or "0, 16" for other interpreters.
359
425
  #
360
426
  # @example
361
427
  # threads 0, 16
@@ -376,8 +442,15 @@ module Puma
376
442
  @options[:max_threads] = max
377
443
  end
378
444
 
379
- # Instead of "bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'" you
380
- # can also use the "ssl_bind" option.
445
+ # Instead of using +bind+ and manually constructing a URI like:
446
+ #
447
+ # bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
448
+ #
449
+ # you can use the this method.
450
+ #
451
+ # When binding on localhost you don't need to specify +cert+ and +key+,
452
+ # Puma will assume you are using the +localhost+ gem and try to load the
453
+ # appropriate files.
381
454
  #
382
455
  # @example
383
456
  # ssl_bind '127.0.0.1', '9292', {
@@ -385,29 +458,28 @@ module Puma
385
458
  # key: path_to_key,
386
459
  # ssl_cipher_filter: cipher_filter, # optional
387
460
  # verify_mode: verify_mode, # default 'none'
461
+ # verification_flags: flags, # optional, not supported by JRuby
388
462
  # }
389
- # @example For JRuby additional keys are required: keystore & keystore_pass.
463
+ #
464
+ # @example Using self-signed certificate with the +localhost+ gem:
465
+ # ssl_bind '127.0.0.1', '9292'
466
+ #
467
+ # @example Alternatively, you can provide +cert_pem+ and +key_pem+:
468
+ # ssl_bind '127.0.0.1', '9292', {
469
+ # cert_pem: File.read(path_to_cert),
470
+ # key_pem: File.read(path_to_key),
471
+ # }
472
+ #
473
+ # @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
390
474
  # ssl_bind '127.0.0.1', '9292', {
391
- # cert: path_to_cert,
392
- # key: path_to_key,
393
- # ssl_cipher_filter: cipher_filter, # optional
394
- # verify_mode: verify_mode, # default 'none'
395
475
  # keystore: path_to_keystore,
396
- # keystore_pass: password
476
+ # keystore_pass: password,
477
+ # ssl_cipher_list: cipher_list, # optional
478
+ # verify_mode: verify_mode # default 'none'
397
479
  # }
398
- def ssl_bind(host, port, opts)
399
- verify = opts.fetch(:verify_mode, 'none').to_s
400
- no_tlsv1 = opts.fetch(:no_tlsv1, 'false')
401
- no_tlsv1_1 = opts.fetch(:no_tlsv1_1, 'false')
402
- ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
403
-
404
- if defined?(JRUBY_VERSION)
405
- keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
406
- bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
407
- else
408
- ssl_cipher_filter = "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" if opts[:ssl_cipher_filter]
409
- bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}#{ssl_cipher_filter}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
410
- end
480
+ def ssl_bind(host, port, opts = {})
481
+ add_pem_values_to_options_store(opts)
482
+ bind self.class.ssl_bind_str(host, port, opts)
411
483
  end
412
484
 
413
485
  # Use +path+ as the file to store the server info state. This is
@@ -419,16 +491,46 @@ module Puma
419
491
  @options[:state] = path.to_s
420
492
  end
421
493
 
494
+ # Use +permission+ to restrict permissions for the state file.
495
+ #
496
+ # @example
497
+ # state_permission 0600
498
+ # @version 5.0.0
499
+ #
500
+ def state_permission(permission)
501
+ @options[:state_permission] = permission
502
+ end
503
+
422
504
  # How many worker processes to run. Typically this is set to
423
- # to the number of available cores.
505
+ # the number of available cores.
424
506
  #
425
- # The default is 0.
507
+ # The default is the value of the environment variable +WEB_CONCURRENCY+ if
508
+ # set, otherwise 0.
426
509
  #
427
510
  # @note Cluster mode only.
511
+ # @see Puma::Cluster
428
512
  def workers(count)
429
513
  @options[:workers] = count.to_i
430
514
  end
431
515
 
516
+ # Disable warning message when running in cluster mode with a single worker.
517
+ #
518
+ # Cluster mode has some overhead of running an additional 'control' process
519
+ # in order to manage the cluster. If only running a single worker it is
520
+ # likely not worth paying that overhead vs running in single mode with
521
+ # additional threads instead.
522
+ #
523
+ # There are some scenarios where running cluster mode with a single worker
524
+ # may still be warranted and valid under certain deployment scenarios, see
525
+ # https://github.com/puma/puma/issues/2534
526
+ #
527
+ # Moving from workers = 1 to workers = 0 will save 10-30% of memory use.
528
+ #
529
+ # @note Cluster mode only.
530
+ def silence_single_worker_warning
531
+ @options[:silence_single_worker_warning] = true
532
+ end
533
+
432
534
  # Code to run immediately before master process
433
535
  # forks workers (once on boot). These hooks can block if necessary
434
536
  # to wait for background operations unknown to Puma to finish before
@@ -455,8 +557,8 @@ module Puma
455
557
  #
456
558
  # @note Cluster mode only.
457
559
  # @example
458
- # on_worker_fork do
459
- # puts 'Before worker fork...'
560
+ # on_worker_boot do
561
+ # puts 'Before worker boot...'
460
562
  # end
461
563
  def on_worker_boot(&block)
462
564
  @options[:before_worker_boot] ||= []
@@ -507,11 +609,34 @@ module Puma
507
609
  # end
508
610
  def after_worker_fork(&block)
509
611
  @options[:after_worker_fork] ||= []
510
- @options[:after_worker_fork] = block
612
+ @options[:after_worker_fork] << block
511
613
  end
512
614
 
513
615
  alias_method :after_worker_boot, :after_worker_fork
514
616
 
617
+ # When `fork_worker` is enabled, code to run in Worker 0
618
+ # before all other workers are re-forked from this process,
619
+ # after the server has temporarily stopped serving requests
620
+ # (once per complete refork cycle).
621
+ #
622
+ # This can be used to trigger extra garbage-collection to maximize
623
+ # copy-on-write efficiency, or close any connections to remote servers
624
+ # (database, Redis, ...) that were opened while the server was running.
625
+ #
626
+ # This can be called multiple times to add several hooks.
627
+ #
628
+ # @note Cluster mode with `fork_worker` enabled only.
629
+ # @example
630
+ # on_refork do
631
+ # 3.times {GC.start}
632
+ # end
633
+ # @version 5.0.0
634
+ #
635
+ def on_refork(&block)
636
+ @options[:before_refork] ||= []
637
+ @options[:before_refork] << block
638
+ end
639
+
515
640
  # Code to run out-of-band when the worker is idle.
516
641
  # These hooks run immediately after a request has finished
517
642
  # processing and there are no busy threads on the worker.
@@ -536,19 +661,8 @@ module Puma
536
661
  @options[:directory] = dir.to_s
537
662
  end
538
663
 
539
- # DEPRECATED: The directory to operate out of.
540
- def worker_directory(dir)
541
- $stderr.puts "worker_directory is deprecated. Please use `directory`"
542
- directory dir
543
- end
544
-
545
- # Run the app as a raw TCP app instead of an HTTP rack app.
546
- def tcp_mode
547
- @options[:mode] = :tcp
548
- end
549
-
550
664
  # Preload the application before starting the workers; this conflicts with
551
- # phased restart feature. This is off by default.
665
+ # phased restart feature. On by default if your app uses more than 1 worker.
552
666
  #
553
667
  # @note Cluster mode only.
554
668
  # @example
@@ -583,7 +697,7 @@ module Puma
583
697
  # new Bundler context and thus can float around as the release
584
698
  # dictates.
585
699
  #
586
- # See also: extra_runtime_dependencies
700
+ # @see extra_runtime_dependencies
587
701
  #
588
702
  # @note This is incompatible with +preload_app!+.
589
703
  # @note This is only supported for RubyGems 2.2+
@@ -600,6 +714,9 @@ module Puma
600
714
  #
601
715
  # @example
602
716
  # raise_exception_on_sigterm false
717
+ # @see Puma::Launcher#setup_signals
718
+ # @see Puma::Cluster#setup_signals
719
+ #
603
720
  def raise_exception_on_sigterm(answer=true)
604
721
  @options[:raise_exception_on_sigterm] = answer
605
722
  end
@@ -615,6 +732,8 @@ module Puma
615
732
  # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
616
733
  # @example
617
734
  # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
735
+ # @see Puma::Launcher#extra_runtime_deps_directories
736
+ #
618
737
  def extra_runtime_dependencies(answer = [])
619
738
  @options[:extra_runtime_dependencies] = Array(answer)
620
739
  end
@@ -632,6 +751,19 @@ module Puma
632
751
  @options[:tag] = string.to_s
633
752
  end
634
753
 
754
+ # Change the default interval for checking workers.
755
+ #
756
+ # The default value is 5 seconds.
757
+ #
758
+ # @note Cluster mode only.
759
+ # @example
760
+ # worker_check_interval 5
761
+ # @see Puma::Cluster#check_workers
762
+ #
763
+ def worker_check_interval(interval)
764
+ @options[:worker_check_interval] = Integer(interval)
765
+ end
766
+
635
767
  # Verifies that all workers have checked in to the master process within
636
768
  # the given timeout. If not the worker process will be restarted. This is
637
769
  # not a request timeout, it is to protect against a hung or dead process.
@@ -642,9 +774,11 @@ module Puma
642
774
  # @note Cluster mode only.
643
775
  # @example
644
776
  # worker_timeout 60
777
+ # @see Puma::Cluster::Worker#ping_timeout
778
+ #
645
779
  def worker_timeout(timeout)
646
780
  timeout = Integer(timeout)
647
- min = Const::WORKER_CHECK_INTERVAL
781
+ min = @options.fetch(:worker_check_interval, Puma::ConfigDefault::DefaultWorkerCheckInterval)
648
782
 
649
783
  if timeout <= min
650
784
  raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
@@ -658,19 +792,48 @@ module Puma
658
792
  # If unspecified, this defaults to the value of worker_timeout.
659
793
  #
660
794
  # @note Cluster mode only.
661
- # @example:
795
+ #
796
+ # @example
662
797
  # worker_boot_timeout 60
798
+ # @see Puma::Cluster::Worker#ping_timeout
799
+ #
663
800
  def worker_boot_timeout(timeout)
664
801
  @options[:worker_boot_timeout] = Integer(timeout)
665
802
  end
666
803
 
667
- # Set the timeout for worker shutdown
804
+ # Set the timeout for worker shutdown.
668
805
  #
669
806
  # @note Cluster mode only.
807
+ # @see Puma::Cluster::Worker#term
808
+ #
670
809
  def worker_shutdown_timeout(timeout)
671
810
  @options[:worker_shutdown_timeout] = Integer(timeout)
672
811
  end
673
812
 
813
+ # Set the strategy for worker culling.
814
+ #
815
+ # There are two possible values:
816
+ #
817
+ # 1. **:youngest** - the youngest workers (i.e. the workers that were
818
+ # the most recently started) will be culled.
819
+ # 2. **:oldest** - the oldest workers (i.e. the workers that were started
820
+ # the longest time ago) will be culled.
821
+ #
822
+ # @note Cluster mode only.
823
+ # @example
824
+ # worker_culling_strategy :oldest
825
+ # @see Puma::Cluster#cull_workers
826
+ #
827
+ def worker_culling_strategy(strategy)
828
+ stategy = strategy.to_sym
829
+
830
+ if ![:youngest, :oldest].include?(strategy)
831
+ raise "Invalid value for worker_culling_strategy - #{stategy}"
832
+ end
833
+
834
+ @options[:worker_culling_strategy] = strategy
835
+ end
836
+
674
837
  # When set to true (the default), workers accept all requests
675
838
  # and queue them before passing them to the handlers.
676
839
  # When set to false, each worker process accepts exactly as
@@ -684,6 +847,7 @@ module Puma
684
847
  # slow clients will occupy a handler thread while the request
685
848
  # is being sent. A reverse proxy, such as nginx, can handle
686
849
  # slow clients and queue requests before they reach Puma.
850
+ # @see Puma::Server
687
851
  def queue_requests(answer=true)
688
852
  @options[:queue_requests] = answer
689
853
  end
@@ -691,29 +855,47 @@ module Puma
691
855
  # When a shutdown is requested, the backtraces of all the
692
856
  # threads will be written to $stdout. This can help figure
693
857
  # out why shutdown is hanging.
858
+ #
694
859
  def shutdown_debug(val=true)
695
860
  @options[:shutdown_debug] = val
696
861
  end
697
862
 
863
+
864
+ # Attempts to route traffic to less-busy workers by causing them to delay
865
+ # listening on the socket, allowing workers which are not processing any
866
+ # requests to pick up new requests first.
867
+ #
868
+ # Only works on MRI. For all other interpreters, this setting does nothing.
869
+ # @see Puma::Server#handle_servers
870
+ # @see Puma::ThreadPool#wait_for_less_busy_worker
871
+ # @version 5.0.0
872
+ #
873
+ def wait_for_less_busy_worker(val=0.005)
874
+ @options[:wait_for_less_busy_worker] = val.to_f
875
+ end
876
+
698
877
  # Control how the remote address of the connection is set. This
699
878
  # is configurable because to calculate the true socket peer address
700
879
  # a kernel syscall is required which for very fast rack handlers
701
880
  # slows down the handling significantly.
702
881
  #
703
- # There are 4 possible values:
704
- #
705
- # * :socket (the default) - read the peername from the socket using the
706
- # syscall. This is the normal behavior.
707
- # * :localhost - set the remote address to "127.0.0.1"
708
- # * header: http_header - set the remote address to the value of the
709
- # provided http header. For instance:
710
- # `set_remote_address header: "X-Real-IP"`.
711
- # Only the first word (as separated by spaces or comma)
712
- # is used, allowing headers such as X-Forwarded-For
713
- # to be used as well.
714
- # * Any string - this allows you to hardcode remote address to any value
715
- # you wish. Because Puma never uses this field anyway, it's
716
- # format is entirely in your hands.
882
+ # There are 5 possible values:
883
+ #
884
+ # 1. **:socket** (the default) - read the peername from the socket using the
885
+ # syscall. This is the normal behavior.
886
+ # 2. **:localhost** - set the remote address to "127.0.0.1"
887
+ # 3. **header: <http_header>**- set the remote address to the value of the
888
+ # provided http header. For instance:
889
+ # `set_remote_address header: "X-Real-IP"`.
890
+ # Only the first word (as separated by spaces or comma) is used, allowing
891
+ # headers such as X-Forwarded-For to be used as well.
892
+ # 4. **proxy_protocol: :v1**- set the remote address to the value read from the
893
+ # HAproxy PROXY protocol, version 1. If the request does not have the PROXY
894
+ # protocol attached to it, will fall back to :socket
895
+ # 5. **\<Any string\>** - this allows you to hardcode remote address to any value
896
+ # you wish. Because Puma never uses this field anyway, it's format is
897
+ # entirely in your hands.
898
+ #
717
899
  def set_remote_address(val=:socket)
718
900
  case val
719
901
  when :socket
@@ -728,6 +910,13 @@ module Puma
728
910
  if hdr = val[:header]
729
911
  @options[:remote_address] = :header
730
912
  @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
913
+ elsif protocol_version = val[:proxy_protocol]
914
+ @options[:remote_address] = :proxy_protocol
915
+ protocol_version = protocol_version.downcase.to_sym
916
+ unless [:v1].include?(protocol_version)
917
+ raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
918
+ end
919
+ @options[:remote_address_proxy_protocol] = protocol_version
731
920
  else
732
921
  raise "Invalid value for set_remote_address - #{val.inspect}"
733
922
  end
@@ -736,5 +925,88 @@ module Puma
736
925
  end
737
926
  end
738
927
 
928
+ # When enabled, workers will be forked from worker 0 instead of from the master process.
929
+ # This option is similar to `preload_app` because the app is preloaded before forking,
930
+ # but it is compatible with phased restart.
931
+ #
932
+ # This option also enables the `refork` command (SIGURG), which optimizes copy-on-write performance
933
+ # in a running app.
934
+ #
935
+ # A refork will automatically trigger once after the specified number of requests
936
+ # (default 1000), or pass 0 to disable auto refork.
937
+ #
938
+ # @note Cluster mode only.
939
+ # @version 5.0.0
940
+ #
941
+ def fork_worker(after_requests=1000)
942
+ @options[:fork_worker] = Integer(after_requests)
943
+ end
944
+
945
+ # When enabled, Puma will GC 4 times before forking workers.
946
+ # If available (Ruby 2.7+), we will also call GC.compact.
947
+ # Not recommended for non-MRI Rubies.
948
+ #
949
+ # Based on the work of Koichi Sasada and Aaron Patterson, this option may
950
+ # decrease memory utilization of preload-enabled cluster-mode Pumas. It will
951
+ # also increase time to boot and fork. See your logs for details on how much
952
+ # time this adds to your boot process. For most apps, it will be less than one
953
+ # second.
954
+ #
955
+ # @see Puma::Cluster#nakayoshi_gc
956
+ # @version 5.0.0
957
+ #
958
+ def nakayoshi_fork(enabled=true)
959
+ @options[:nakayoshi_fork] = enabled
960
+ end
961
+
962
+ # The number of requests to attempt inline before sending a client back to
963
+ # the reactor to be subject to normal ordering.
964
+ #
965
+ def max_fast_inline(num_of_requests)
966
+ @options[:max_fast_inline] = Float(num_of_requests)
967
+ end
968
+
969
+ # Specify the backend for the IO selector.
970
+ #
971
+ # Provided values will be passed directly to +NIO::Selector.new+, with the
972
+ # exception of +:auto+ which will let nio4r choose the backend.
973
+ #
974
+ # Check the documentation of +NIO::Selector.backends+ for the list of valid
975
+ # options. Note that the available options on your system will depend on the
976
+ # operating system. If you want to use the pure Ruby backend (not
977
+ # recommended due to its comparatively low performance), set environment
978
+ # variable +NIO4R_PURE+ to +true+.
979
+ #
980
+ # The default is +:auto+.
981
+ #
982
+ # @see https://github.com/socketry/nio4r/blob/master/lib/nio/selector.rb
983
+ #
984
+ def io_selector_backend(backend)
985
+ @options[:io_selector_backend] = backend.to_sym
986
+ end
987
+
988
+ def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
989
+ @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
990
+ end
991
+
992
+ private
993
+
994
+ # To avoid adding cert_pem and key_pem as URI params, we store them on the
995
+ # options[:store] from where Puma binder knows how to find and extract them.
996
+ def add_pem_values_to_options_store(opts)
997
+ return if defined?(JRUBY_VERSION)
998
+
999
+ @options[:store] ||= []
1000
+
1001
+ # Store cert_pem and key_pem to options[:store] if present
1002
+ [:cert, :key].each do |v|
1003
+ opt_key = :"#{v}_pem"
1004
+ if opts[opt_key]
1005
+ index = @options[:store].length
1006
+ @options[:store] << opts[opt_key]
1007
+ opts[v] = "store:#{index}"
1008
+ end
1009
+ end
1010
+ end
739
1011
  end
740
1012
  end