puma 6.4.1 → 7.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +407 -8
  3. data/README.md +109 -49
  4. data/docs/deployment.md +58 -23
  5. data/docs/fork_worker.md +11 -1
  6. data/docs/java_options.md +54 -0
  7. data/docs/jungle/README.md +1 -1
  8. data/docs/kubernetes.md +11 -16
  9. data/docs/plugins.md +6 -2
  10. data/docs/restart.md +2 -2
  11. data/docs/signals.md +21 -21
  12. data/docs/stats.md +11 -5
  13. data/docs/systemd.md +14 -5
  14. data/ext/puma_http11/extconf.rb +20 -32
  15. data/ext/puma_http11/mini_ssl.c +29 -9
  16. data/ext/puma_http11/org/jruby/puma/Http11.java +40 -9
  17. data/ext/puma_http11/puma_http11.c +125 -118
  18. data/lib/puma/app/status.rb +11 -3
  19. data/lib/puma/binder.rb +21 -11
  20. data/lib/puma/cli.rb +10 -8
  21. data/lib/puma/client.rb +183 -83
  22. data/lib/puma/cluster/worker.rb +24 -21
  23. data/lib/puma/cluster/worker_handle.rb +38 -8
  24. data/lib/puma/cluster.rb +73 -47
  25. data/lib/puma/cluster_accept_loop_delay.rb +91 -0
  26. data/lib/puma/commonlogger.rb +3 -3
  27. data/lib/puma/configuration.rb +131 -60
  28. data/lib/puma/const.rb +31 -12
  29. data/lib/puma/control_cli.rb +10 -6
  30. data/lib/puma/detect.rb +2 -0
  31. data/lib/puma/dsl.rb +411 -121
  32. data/lib/puma/error_logger.rb +7 -5
  33. data/lib/puma/events.rb +25 -10
  34. data/lib/puma/io_buffer.rb +8 -4
  35. data/lib/puma/jruby_restart.rb +0 -16
  36. data/lib/puma/launcher/bundle_pruner.rb +1 -1
  37. data/lib/puma/launcher.rb +73 -55
  38. data/lib/puma/log_writer.rb +9 -9
  39. data/lib/puma/minissl/context_builder.rb +1 -0
  40. data/lib/puma/minissl.rb +1 -1
  41. data/lib/puma/null_io.rb +26 -0
  42. data/lib/puma/plugin/systemd.rb +3 -3
  43. data/lib/puma/rack/urlmap.rb +1 -1
  44. data/lib/puma/reactor.rb +19 -13
  45. data/lib/puma/request.rb +71 -39
  46. data/lib/puma/runner.rb +15 -17
  47. data/lib/puma/sd_notify.rb +1 -4
  48. data/lib/puma/server.rb +134 -73
  49. data/lib/puma/single.rb +7 -4
  50. data/lib/puma/state_file.rb +3 -2
  51. data/lib/puma/thread_pool.rb +57 -80
  52. data/lib/puma/util.rb +0 -7
  53. data/lib/puma.rb +10 -0
  54. data/lib/rack/handler/puma.rb +10 -7
  55. data/tools/Dockerfile +15 -5
  56. metadata +14 -15
  57. data/ext/puma_http11/ext_help.h +0 -15
data/lib/puma/dsl.rb CHANGED
@@ -13,7 +13,7 @@ module Puma
13
13
  # config = Configuration.new({}) do |user_config|
14
14
  # user_config.port 3001
15
15
  # end
16
- # config.load
16
+ # config.clamp
17
17
  #
18
18
  # puts config.options[:binds] # => "tcp://127.0.0.1:3001"
19
19
  #
@@ -25,7 +25,7 @@ module Puma
25
25
  # Resulting configuration:
26
26
  #
27
27
  # config = Configuration.new(config_file: "puma_config.rb")
28
- # config.load
28
+ # config.clamp
29
29
  #
30
30
  # puts config.options[:binds] # => "tcp://127.0.0.1:3002"
31
31
  #
@@ -43,15 +43,17 @@ module Puma
43
43
  #
44
44
  # The following hooks have been updated:
45
45
  #
46
- # | DSL Method | Options Key | Fork Block Location |
47
- # | on_worker_boot | :before_worker_boot | inside, before |
48
- # | on_worker_shutdown | :before_worker_shutdown | inside, after |
49
- # | on_refork | :before_refork | inside |
46
+ # | DSL Method | Options Key | Fork Block Location |
47
+ # | before_worker_boot | :before_worker_boot | inside, before |
48
+ # | before_worker_shutdown | :before_worker_shutdown | inside, after |
49
+ # | before_refork | :before_refork | inside |
50
+ # | after_refork | :after_refork | inside |
50
51
  #
51
52
  class DSL
52
53
  ON_WORKER_KEY = [String, Symbol].freeze
53
54
 
54
- # convenience method so logic can be used in CI
55
+ # Convenience method so logic can be used in CI.
56
+ #
55
57
  # @see ssl_bind
56
58
  #
57
59
  def self.ssl_bind_str(host, port, opts)
@@ -85,6 +87,7 @@ module Puma
85
87
  "&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
86
88
  else
87
89
  ssl_cipher_filter = opts[:ssl_cipher_filter] ? "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
90
+ ssl_ciphersuites = opts[:ssl_ciphersuites] ? "&ssl_ciphersuites=#{opts[:ssl_ciphersuites]}" : nil
88
91
  v_flags = (ary = opts[:verification_flags]) ? "&verification_flags=#{Array(ary).join ','}" : nil
89
92
 
90
93
  cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(cert)}" : nil
@@ -115,7 +118,7 @@ module Puma
115
118
  nil
116
119
  end
117
120
 
118
- "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{password_flags}#{ssl_cipher_filter}" \
121
+ "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{password_flags}#{ssl_cipher_filter}#{ssl_ciphersuites}" \
119
122
  "#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}#{low_latency_str}"
120
123
  end
121
124
  end
@@ -163,7 +166,10 @@ module Puma
163
166
  @options[key.to_sym] || default
164
167
  end
165
168
 
166
- # Load the named plugin for use by this configuration
169
+ # Load the named plugin for use by this configuration.
170
+ #
171
+ # @example
172
+ # plugin :tmp_restart
167
173
  #
168
174
  def plugin(name)
169
175
  @plugins << @config.load_plugin(name)
@@ -210,6 +216,9 @@ module Puma
210
216
  # activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
211
217
  # @example
212
218
  # activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
219
+ # @example
220
+ # activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true, data_only: true}
221
+ #
213
222
  def activate_control_app(url="auto", opts={})
214
223
  if url == "auto"
215
224
  path = Configuration.temp_path
@@ -233,10 +242,15 @@ module Puma
233
242
 
234
243
  @options[:control_auth_token] = auth_token
235
244
  @options[:control_url_umask] = opts[:umask] if opts[:umask]
245
+ @options[:control_data_only] = opts[:data_only] if opts[:data_only]
236
246
  end
237
247
 
238
- # Load additional configuration from a file
239
- # Files get loaded later via Configuration#load
248
+ # Load additional configuration from a file.
249
+ # Files get loaded later via Configuration#load.
250
+ #
251
+ # @example
252
+ # load 'config/puma/production.rb'
253
+ #
240
254
  def load(file)
241
255
  @options[:config_files] ||= []
242
256
  @options[:config_files] << file
@@ -268,6 +282,7 @@ module Puma
268
282
  # bind 'tcp://0.0.0.0:9292?low_latency=false'
269
283
  # @example Socket permissions
270
284
  # bind 'unix:///var/run/puma.sock?umask=0111'
285
+ #
271
286
  # @see Puma::Runner#load_and_bind
272
287
  # @see Puma::Cluster#run
273
288
  #
@@ -302,46 +317,81 @@ module Puma
302
317
  #
303
318
  # @example Only bind to systemd activated sockets, ignoring other binds
304
319
  # bind_to_activated_sockets 'only'
320
+ #
305
321
  def bind_to_activated_sockets(bind=true)
306
322
  @options[:bind_to_activated_sockets] = bind
307
323
  end
308
324
 
309
- # Define the TCP port to bind to. Use +bind+ for more advanced options.
325
+ # Define the TCP port to bind to. Use `bind` for more advanced options.
326
+ #
327
+ # The default is +9292+.
310
328
  #
311
329
  # @example
312
- # port 9292
330
+ # port 3000
331
+ #
313
332
  def port(port, host=nil)
314
333
  host ||= default_host
315
334
  bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
316
335
  end
317
336
 
318
337
  # Define how long the tcp socket stays open, if no data has been received.
338
+ #
339
+ # The default is 30 seconds.
340
+ #
341
+ # @example
342
+ # first_data_timeout 40
343
+ #
319
344
  # @see Puma::Server.new
345
+ #
320
346
  def first_data_timeout(seconds)
321
347
  @options[:first_data_timeout] = Integer(seconds)
322
348
  end
323
349
 
324
350
  # Define how long persistent connections can be idle before Puma closes them.
351
+ #
352
+ # The default is 20 seconds.
353
+ #
354
+ # @example
355
+ # persistent_timeout 30
356
+ #
325
357
  # @see Puma::Server.new
358
+ #
326
359
  def persistent_timeout(seconds)
327
360
  @options[:persistent_timeout] = Integer(seconds)
328
361
  end
329
362
 
330
363
  # If a new request is not received within this number of seconds, begin shutting down.
364
+ #
365
+ # The default is +nil+.
366
+ #
367
+ # @example
368
+ # idle_timeout 60
369
+ #
331
370
  # @see Puma::Server.new
371
+ #
332
372
  def idle_timeout(seconds)
333
373
  @options[:idle_timeout] = Integer(seconds)
334
374
  end
335
375
 
336
- # Work around leaky apps that leave garbage in Thread locals
337
- # across requests.
338
- def clean_thread_locals(which=true)
339
- @options[:clean_thread_locals] = which
376
+ # Use a clean fiber per request which ensures a clean slate for fiber
377
+ # locals and fiber storage. Also provides a cleaner backtrace with less
378
+ # Puma internal stack frames.
379
+ #
380
+ # The default is +false+.
381
+ #
382
+ # @example
383
+ # fiber_per_request
384
+ #
385
+ def fiber_per_request(which=true)
386
+ @options[:fiber_per_request] = which
340
387
  end
341
388
 
389
+ alias clean_thread_locals fiber_per_request
390
+
342
391
  # When shutting down, drain the accept socket of pending connections and
343
392
  # process them. This loops over the accept socket until there are no more
344
393
  # read events and then stops looking and waits for the requests to finish.
394
+ #
345
395
  # @see Puma::Server#graceful_shutdown
346
396
  #
347
397
  def drain_on_shutdown(which=true)
@@ -355,18 +405,22 @@ module Puma
355
405
  #
356
406
  # @example
357
407
  # environment 'production'
408
+ #
358
409
  def environment(environment)
359
410
  @options[:environment] = environment
360
411
  end
361
412
 
362
- # How long to wait for threads to stop when shutting them
363
- # down. Defaults to :forever. Specifying :immediately will cause
364
- # Puma to kill the threads immediately. Otherwise the value
365
- # is the number of seconds to wait.
413
+ # How long to wait for threads to stop when shutting them down.
414
+ # Specifying :immediately will cause Puma to kill the threads immediately.
415
+ # Otherwise the value is the number of seconds to wait.
366
416
  #
367
417
  # Puma always waits a few seconds after killing a thread for it to try
368
418
  # to finish up it's work, even in :immediately mode.
419
+ #
420
+ # The default is +:forever+.
421
+ #
369
422
  # @see Puma::Server#graceful_shutdown
423
+ #
370
424
  def force_shutdown_after(val=:forever)
371
425
  i = case val
372
426
  when :forever
@@ -386,20 +440,25 @@ module Puma
386
440
  # This can be called multiple times to add code each time.
387
441
  #
388
442
  # @example
389
- # on_restart do
443
+ # before_restart do
390
444
  # puts 'On restart...'
391
445
  # end
392
- def on_restart(&block)
393
- @options[:on_restart] ||= []
394
- @options[:on_restart] << block
446
+ #
447
+ def before_restart(&block)
448
+ Puma.deprecate_method_change :on_restart, __callee__, __method__
449
+
450
+ process_hook :before_restart, nil, block
395
451
  end
396
452
 
453
+ alias_method :on_restart, :before_restart
454
+
397
455
  # Command to use to restart Puma. This should be just how to
398
456
  # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
399
457
  # to Puma, as those are the same as the original process.
400
458
  #
401
459
  # @example
402
460
  # restart_command '/u/app/lolcat/bin/restart_puma'
461
+ #
403
462
  def restart_command(cmd)
404
463
  @options[:restart_cmd] = cmd.to_s
405
464
  end
@@ -408,31 +467,49 @@ module Puma
408
467
  #
409
468
  # @example
410
469
  # pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
470
+ #
411
471
  def pidfile(path)
412
472
  @options[:pidfile] = path.to_s
413
473
  end
414
474
 
415
- # Disable request logging, if this isn't used it'll be enabled by default.
475
+ # Disable request logging, the inverse of `log_requests`.
476
+ #
477
+ # The default is +true+.
416
478
  #
417
479
  # @example
418
480
  # quiet
481
+ #
419
482
  def quiet(which=true)
420
483
  @options[:log_requests] = !which
421
484
  end
422
485
 
423
- # Enable request logging
486
+ # Enable request logging, the inverse of `quiet`.
487
+ #
488
+ # The default is +false+.
489
+ #
490
+ # @example
491
+ # log_requests
424
492
  #
425
493
  def log_requests(which=true)
426
494
  @options[:log_requests] = which
427
495
  end
428
496
 
429
497
  # Pass in a custom logging class instance
498
+ #
499
+ # @example
500
+ # custom_logger Logger.new('t.log')
501
+ #
430
502
  def custom_logger(custom_logger)
431
503
  @options[:custom_logger] = custom_logger
432
504
  end
433
505
 
434
506
  # Show debugging info
435
507
  #
508
+ # The default is +false+.
509
+ #
510
+ # @example
511
+ # debug
512
+ #
436
513
  def debug
437
514
  @options[:debug] = true
438
515
  end
@@ -443,6 +520,7 @@ module Puma
443
520
  #
444
521
  # @example
445
522
  # rackup '/u/apps/lolcat/config.ru'
523
+ #
446
524
  def rackup(path)
447
525
  @options[:rackup] ||= path.to_s
448
526
  end
@@ -450,21 +528,32 @@ module Puma
450
528
  # Allows setting `env['rack.url_scheme']`.
451
529
  # Only necessary if X-Forwarded-Proto is not being set by your proxy
452
530
  # Normal values are 'http' or 'https'.
531
+ #
453
532
  def rack_url_scheme(scheme=nil)
454
533
  @options[:rack_url_scheme] = scheme
455
534
  end
456
535
 
536
+ # Enable HTTP 103 Early Hints responses.
537
+ #
538
+ # The default is +nil+.
539
+ #
540
+ # @example
541
+ # early_hints
542
+ #
457
543
  def early_hints(answer=true)
458
544
  @options[:early_hints] = answer
459
545
  end
460
546
 
461
547
  # Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
462
- # specifies whether the output is appended, the default is +false+.
548
+ # specifies whether the output is appended.
549
+ #
550
+ # The default is +false+.
463
551
  #
464
552
  # @example
465
553
  # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
466
554
  # @example
467
555
  # stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
556
+ #
468
557
  def stdout_redirect(stdout=nil, stderr=nil, append=false)
469
558
  @options[:redirect_stdout] = stdout
470
559
  @options[:redirect_stderr] = stderr
@@ -475,8 +564,9 @@ module Puma
475
564
  @options[:log_formatter] = block
476
565
  end
477
566
 
478
- # Configure +min+ to be the minimum number of threads to use to answer
479
- # requests and +max+ the maximum.
567
+ # Configure the number of threads to use to answer requests.
568
+ #
569
+ # It can be a single fixed number, or a +min+ and a +max+.
480
570
  #
481
571
  # The default is the environment variables +PUMA_MIN_THREADS+ / +PUMA_MAX_THREADS+
482
572
  # (or +MIN_THREADS+ / +MAX_THREADS+ if the +PUMA_+ variables aren't set).
@@ -484,10 +574,13 @@ module Puma
484
574
  # If these environment variables aren't set, the default is "0, 5" in MRI or "0, 16" for other interpreters.
485
575
  #
486
576
  # @example
577
+ # threads 5
578
+ # @example
487
579
  # threads 0, 16
488
580
  # @example
489
581
  # threads 5, 5
490
- def threads(min, max)
582
+ #
583
+ def threads(min, max = min)
491
584
  min = Integer(min)
492
585
  max = Integer(max)
493
586
  if min > max
@@ -527,6 +620,7 @@ module Puma
527
620
  # cert: path_to_cert,
528
621
  # key: path_to_key,
529
622
  # ssl_cipher_filter: cipher_filter, # optional
623
+ # ssl_ciphersuites: ciphersuites, # optional
530
624
  # verify_mode: verify_mode, # default 'none'
531
625
  # verification_flags: flags, # optional, not supported by JRuby
532
626
  # reuse: true # optional
@@ -549,6 +643,7 @@ module Puma
549
643
  # ssl_cipher_list: cipher_list, # optional
550
644
  # verify_mode: verify_mode # default 'none'
551
645
  # }
646
+ #
552
647
  def ssl_bind(host, port, opts = {})
553
648
  add_pem_values_to_options_store(opts)
554
649
  bind self.class.ssl_bind_str(host, port, opts)
@@ -559,30 +654,42 @@ module Puma
559
654
  #
560
655
  # @example
561
656
  # state_path '/u/apps/lolcat/tmp/pids/puma.state'
657
+ #
562
658
  def state_path(path)
563
659
  @options[:state] = path.to_s
564
660
  end
565
661
 
566
- # Use +permission+ to restrict permissions for the state file.
662
+ # Use +permission+ to restrict permissions for the state file. By convention,
663
+ # +permission+ is an octal number (e.g. `0640` or `0o640`).
567
664
  #
568
665
  # @example
569
666
  # state_permission 0600
570
- # @version 5.0.0
571
667
  #
572
668
  def state_permission(permission)
573
669
  @options[:state_permission] = permission
574
670
  end
575
671
 
576
- # How many worker processes to run. Typically this is set to
577
- # the number of available cores.
672
+ # How many worker processes to run. Typically this is set to the number of
673
+ # available cores.
578
674
  #
579
675
  # The default is the value of the environment variable +WEB_CONCURRENCY+ if
580
- # set, otherwise 0.
676
+ # set, otherwise 0. Passing +:auto+ will set the value to
677
+ # +Concurrent.available_processor_count+ (requires the concurrent-ruby gem).
678
+ # On some platforms (e.g. under CPU quotas) this may be fractional, and Puma
679
+ # will round down. If it rounds down to 0, Puma will run in single mode and
680
+ # cluster-only hooks like +before_worker_boot+ will not execute.
681
+ # If you rely on cluster-only hooks, set an explicit worker count.
682
+ #
683
+ # A value of 0 or nil means run in single mode.
684
+ #
685
+ # @example
686
+ # workers 2
687
+ # workers :auto
581
688
  #
582
- # @note Cluster mode only.
583
689
  # @see Puma::Cluster
690
+ #
584
691
  def workers(count)
585
- @options[:workers] = count.to_i
692
+ @options[:workers] = count.nil? ? 0 : @config.send(:parse_workers, count)
586
693
  end
587
694
 
588
695
  # Disable warning message when running in cluster mode with a single worker.
@@ -598,12 +705,24 @@ module Puma
598
705
  #
599
706
  # Moving from workers = 1 to workers = 0 will save 10-30% of memory use.
600
707
  #
708
+ # The default is +false+.
709
+ #
601
710
  # @note Cluster mode only.
711
+ #
712
+ # @example
713
+ # silence_single_worker_warning
714
+ #
602
715
  def silence_single_worker_warning
603
716
  @options[:silence_single_worker_warning] = true
604
717
  end
605
718
 
606
719
  # Disable warning message when running single mode with callback hook defined.
720
+ #
721
+ # The default is +false+.
722
+ #
723
+ # @example
724
+ # silence_fork_callback_warning
725
+ #
607
726
  def silence_fork_callback_warning
608
727
  @options[:silence_fork_callback_warning] = true
609
728
  end
@@ -618,15 +737,14 @@ module Puma
618
737
  # This can be called multiple times to add several hooks.
619
738
  #
620
739
  # @note Cluster mode only.
740
+ #
621
741
  # @example
622
742
  # before_fork do
623
743
  # puts "Starting workers..."
624
744
  # end
745
+ #
625
746
  def before_fork(&block)
626
- warn_if_in_single_mode('before_fork')
627
-
628
- @options[:before_fork] ||= []
629
- @options[:before_fork] << block
747
+ process_hook :before_fork, nil, block, cluster_only: true
630
748
  end
631
749
 
632
750
  # Code to run in a worker when it boots to setup
@@ -635,77 +753,123 @@ module Puma
635
753
  # This can be called multiple times to add several hooks.
636
754
  #
637
755
  # @note Cluster mode only.
756
+ #
638
757
  # @example
639
- # on_worker_boot do
758
+ # before_worker_boot do
640
759
  # puts 'Before worker boot...'
641
760
  # end
642
- def on_worker_boot(key = nil, &block)
643
- warn_if_in_single_mode('on_worker_boot')
761
+ #
762
+ def before_worker_boot(key = nil, &block)
763
+ Puma.deprecate_method_change :on_worker_boot, __callee__, __method__
644
764
 
645
- process_hook :before_worker_boot, key, block, 'on_worker_boot'
765
+ process_hook :before_worker_boot, key, block, cluster_only: true
646
766
  end
647
767
 
768
+ alias_method :on_worker_boot, :before_worker_boot
769
+
648
770
  # Code to run immediately before a worker shuts
649
- # down (after it has finished processing HTTP requests). These hooks
771
+ # down (after it has finished processing HTTP requests). The worker's
772
+ # index is passed as an argument. These hooks
650
773
  # can block if necessary to wait for background operations unknown
651
774
  # to Puma to finish before the process terminates.
652
775
  #
653
776
  # This can be called multiple times to add several hooks.
654
777
  #
655
778
  # @note Cluster mode only.
779
+ #
656
780
  # @example
657
- # on_worker_shutdown do
781
+ # before_worker_shutdown do
658
782
  # puts 'On worker shutdown...'
659
783
  # end
660
- def on_worker_shutdown(key = nil, &block)
661
- warn_if_in_single_mode('on_worker_shutdown')
784
+ #
785
+ def before_worker_shutdown(key = nil, &block)
786
+ Puma.deprecate_method_change :on_worker_shutdown, __callee__, __method__
662
787
 
663
- process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
788
+ process_hook :before_worker_shutdown, key, block, cluster_only: true
664
789
  end
665
790
 
791
+ alias_method :on_worker_shutdown, :before_worker_shutdown
792
+
666
793
  # Code to run in the master right before a worker is started. The worker's
667
794
  # index is passed as an argument.
668
795
  #
669
796
  # This can be called multiple times to add several hooks.
670
797
  #
671
798
  # @note Cluster mode only.
799
+ #
672
800
  # @example
673
- # on_worker_fork do
801
+ # before_worker_fork do
674
802
  # puts 'Before worker fork...'
675
803
  # end
676
- def on_worker_fork(&block)
677
- warn_if_in_single_mode('on_worker_fork')
804
+ #
805
+ def before_worker_fork(&block)
806
+ Puma.deprecate_method_change :on_worker_fork, __callee__, __method__
678
807
 
679
- process_hook :before_worker_fork, nil, block, 'on_worker_fork'
808
+ process_hook :before_worker_fork, nil, block, cluster_only: true
680
809
  end
681
810
 
811
+ alias_method :on_worker_fork, :before_worker_fork
812
+
682
813
  # Code to run in the master after a worker has been started. The worker's
683
814
  # index is passed as an argument.
684
815
  #
685
816
  # This is called everytime a worker is to be started.
686
817
  #
687
818
  # @note Cluster mode only.
819
+ #
688
820
  # @example
689
821
  # after_worker_fork do
690
822
  # puts 'After worker fork...'
691
823
  # end
824
+ #
692
825
  def after_worker_fork(&block)
693
- warn_if_in_single_mode('after_worker_fork')
694
-
695
- process_hook :after_worker_fork, nil, block, 'after_worker_fork'
826
+ process_hook :after_worker_fork, nil, block, cluster_only: true
696
827
  end
697
828
 
698
829
  alias_method :after_worker_boot, :after_worker_fork
699
830
 
700
- # Code to run after puma is booted (works for both: single and clustered)
831
+ # Code to run in the master right after a worker has stopped. The worker's
832
+ # index and Process::Status are passed as arguments.
833
+ #
834
+ # @note Cluster mode only.
701
835
  #
702
836
  # @example
703
- # on_booted do
837
+ # after_worker_shutdown do |worker_handle|
838
+ # puts 'Worker crashed' unless worker_handle.process_status.success?
839
+ # end
840
+ #
841
+ def after_worker_shutdown(&block)
842
+ process_hook :after_worker_shutdown, nil, block, cluster_only: true
843
+ end
844
+
845
+ # Code to run after puma is booted (works for both single and cluster modes).
846
+ #
847
+ # @example
848
+ # after_booted do
704
849
  # puts 'After booting...'
705
850
  # end
706
- def on_booted(&block)
707
- @config.options[:events].on_booted(&block)
851
+ #
852
+ def after_booted(&block)
853
+ Puma.deprecate_method_change :on_booted, __callee__, __method__
854
+
855
+ @config.events.after_booted(&block)
856
+ end
857
+
858
+ alias_method :on_booted, :after_booted
859
+
860
+ # Code to run after puma is stopped (works for both: single and clustered)
861
+ #
862
+ # @example
863
+ # after_stopped do
864
+ # puts 'After stopping...'
865
+ # end
866
+ #
867
+ def after_stopped(&block)
868
+ Puma.deprecate_method_change :on_stopped, __callee__, __method__
869
+
870
+ @config.events.after_stopped(&block)
708
871
  end
872
+ alias_method :on_stopped, :after_stopped
709
873
 
710
874
  # When `fork_worker` is enabled, code to run in Worker 0
711
875
  # before all other workers are re-forked from this process,
@@ -719,14 +883,41 @@ module Puma
719
883
  # This can be called multiple times to add several hooks.
720
884
  #
721
885
  # @note Cluster mode with `fork_worker` enabled only.
886
+ #
722
887
  # @example
723
- # on_refork do
888
+ # before_refork do
724
889
  # 3.times {GC.start}
725
890
  # end
891
+ #
726
892
  # @version 5.0.0
727
893
  #
728
- def on_refork(key = nil, &block)
729
- process_hook :before_refork, key, block, 'on_refork'
894
+ def before_refork(key = nil, &block)
895
+ Puma.deprecate_method_change :on_refork, __callee__, __method__
896
+
897
+ process_hook :before_refork, key, block, cluster_only: true
898
+ end
899
+
900
+ alias_method :on_refork, :before_refork
901
+
902
+ # When `fork_worker` is enabled, code to run in Worker 0
903
+ # after all other workers are re-forked from this process,
904
+ # after the server has temporarily stopped serving requests
905
+ # (once per complete refork cycle).
906
+ #
907
+ # This can be used to re-open any connections to remote servers
908
+ # (database, Redis, ...) that were closed via before_refork.
909
+ #
910
+ # This can be called multiple times to add several hooks.
911
+ #
912
+ # @note Cluster mode with `fork_worker` enabled only.
913
+ #
914
+ # @example
915
+ # after_refork do
916
+ # puts 'After refork...'
917
+ # end
918
+ #
919
+ def after_refork(key = nil, &block)
920
+ process_hook :after_refork, key, block
730
921
  end
731
922
 
732
923
  # Provide a block to be executed just before a thread is added to the thread
@@ -742,14 +933,18 @@ module Puma
742
933
  # This can be called multiple times to add several hooks.
743
934
  #
744
935
  # @example
745
- # on_thread_start do
936
+ # before_thread_start do
746
937
  # puts 'On thread start...'
747
938
  # end
748
- def on_thread_start(&block)
749
- @options[:before_thread_start] ||= []
750
- @options[:before_thread_start] << block
939
+ #
940
+ def before_thread_start(&block)
941
+ Puma.deprecate_method_change :on_thread_start, __callee__, __method__
942
+
943
+ process_hook :before_thread_start, nil, block
751
944
  end
752
945
 
946
+ alias_method :on_thread_start, :before_thread_start
947
+
753
948
  # Provide a block to be executed after a thread is trimmed from the thread
754
949
  # pool. Be careful: while this block executes, Puma's main loop is
755
950
  # blocked, so no new requests will be picked up.
@@ -766,14 +961,18 @@ module Puma
766
961
  # This can be called multiple times to add several hooks.
767
962
  #
768
963
  # @example
769
- # on_thread_exit do
964
+ # before_thread_exit do
770
965
  # puts 'On thread exit...'
771
966
  # end
772
- def on_thread_exit(&block)
773
- @options[:before_thread_exit] ||= []
774
- @options[:before_thread_exit] << block
967
+ #
968
+ def before_thread_exit(&block)
969
+ Puma.deprecate_method_change :on_thread_exit, __callee__, __method__
970
+
971
+ process_hook :before_thread_exit, nil, block
775
972
  end
776
973
 
974
+ alias_method :on_thread_exit, :before_thread_exit
975
+
777
976
  # Code to run out-of-band when the worker is idle.
778
977
  # These hooks run immediately after a request has finished
779
978
  # processing and there are no busy threads on the worker.
@@ -783,8 +982,9 @@ module Puma
783
982
  # or scheduling asynchronous tasks to execute after a response.
784
983
  #
785
984
  # This can be called multiple times to add several hooks.
985
+ #
786
986
  def out_of_band(&block)
787
- process_hook :out_of_band, nil, block, 'out_of_band'
987
+ process_hook :out_of_band, nil, block
788
988
  end
789
989
 
790
990
  # The directory to operate out of.
@@ -793,16 +993,22 @@ module Puma
793
993
  #
794
994
  # @example
795
995
  # directory '/u/apps/lolcat'
996
+ #
796
997
  def directory(dir)
797
998
  @options[:directory] = dir.to_s
798
999
  end
799
1000
 
800
- # Preload the application before starting the workers; this conflicts with
801
- # phased restart feature. On by default if your app uses more than 1 worker.
1001
+ # Preload the application before forking the workers; this conflicts with
1002
+ # the phased restart feature.
1003
+ #
1004
+ # The default is +true+ if your app uses more than 1 worker.
802
1005
  #
803
1006
  # @note Cluster mode only.
1007
+ # @note When using `fork_worker`, this only applies to worker 0.
1008
+ #
804
1009
  # @example
805
1010
  # preload_app!
1011
+ #
806
1012
  def preload_app!(answer=true)
807
1013
  @options[:preload_app] = answer
808
1014
  end
@@ -814,6 +1020,7 @@ module Puma
814
1020
  # lowlevel_error_handler do |err|
815
1021
  # [200, {}, ["error page"]]
816
1022
  # end
1023
+ #
817
1024
  def lowlevel_error_handler(obj=nil, &block)
818
1025
  obj ||= block
819
1026
  raise "Provide either a #call'able or a block" unless obj
@@ -833,23 +1040,26 @@ module Puma
833
1040
  # new Bundler context and thus can float around as the release
834
1041
  # dictates.
835
1042
  #
836
- # @see extra_runtime_dependencies
837
- #
838
1043
  # @note This is incompatible with +preload_app!+.
839
1044
  # @note This is only supported for RubyGems 2.2+
1045
+ #
1046
+ # @see extra_runtime_dependencies
1047
+ #
840
1048
  def prune_bundler(answer=true)
841
1049
  @options[:prune_bundler] = answer
842
1050
  end
843
1051
 
844
- # By default, Puma will raise SignalException when SIGTERM is received. In
845
- # environments where SIGTERM is something expected, you can suppress these
846
- # with this option.
1052
+ # Raises a SignalException when SIGTERM is received. In environments where
1053
+ # SIGTERM is something expected, you can suppress these with this option.
847
1054
  #
848
1055
  # This can be useful for example in Kubernetes, where rolling restart is
849
- # guaranteed usually on infrastructure level.
1056
+ # guaranteed usually on the infrastructure level.
1057
+ #
1058
+ # The default is +true+.
850
1059
  #
851
1060
  # @example
852
1061
  # raise_exception_on_sigterm false
1062
+ #
853
1063
  # @see Puma::Launcher#setup_signals
854
1064
  # @see Puma::Cluster#setup_signals
855
1065
  #
@@ -868,6 +1078,7 @@ module Puma
868
1078
  # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
869
1079
  # @example
870
1080
  # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
1081
+ #
871
1082
  # @see Puma::Launcher#extra_runtime_deps_directories
872
1083
  #
873
1084
  def extra_runtime_dependencies(answer = [])
@@ -879,21 +1090,26 @@ module Puma
879
1090
  # If you do not specify a tag, Puma will infer it. If you do not want Puma
880
1091
  # to add a tag, use an empty string.
881
1092
  #
1093
+ # The default is the current file or directory base name.
1094
+ #
882
1095
  # @example
883
1096
  # tag 'app name'
884
1097
  # @example
885
1098
  # tag ''
1099
+ #
886
1100
  def tag(string)
887
1101
  @options[:tag] = string.to_s
888
1102
  end
889
1103
 
890
1104
  # Change the default interval for checking workers.
891
1105
  #
892
- # The default value is 5 seconds.
1106
+ # The default is 5 seconds.
893
1107
  #
894
1108
  # @note Cluster mode only.
1109
+ #
895
1110
  # @example
896
- # worker_check_interval 5
1111
+ # worker_check_interval 10
1112
+ #
897
1113
  # @see Puma::Cluster#check_workers
898
1114
  #
899
1115
  def worker_check_interval(interval)
@@ -906,11 +1122,14 @@ module Puma
906
1122
  # Setting this value will not protect against slow requests.
907
1123
  #
908
1124
  # This value must be greater than worker_check_interval.
909
- # The default value is 60 seconds.
1125
+ #
1126
+ # The default is 60 seconds.
910
1127
  #
911
1128
  # @note Cluster mode only.
1129
+ #
912
1130
  # @example
913
1131
  # worker_timeout 60
1132
+ #
914
1133
  # @see Puma::Cluster::Worker#ping_timeout
915
1134
  #
916
1135
  def worker_timeout(timeout)
@@ -926,12 +1145,13 @@ module Puma
926
1145
 
927
1146
  # Change the default worker timeout for booting.
928
1147
  #
929
- # If unspecified, this defaults to the value of worker_timeout.
1148
+ # The default is the value of `worker_timeout`.
930
1149
  #
931
1150
  # @note Cluster mode only.
932
1151
  #
933
1152
  # @example
934
1153
  # worker_boot_timeout 60
1154
+ #
935
1155
  # @see Puma::Cluster::Worker#ping_timeout
936
1156
  #
937
1157
  def worker_boot_timeout(timeout)
@@ -940,7 +1160,13 @@ module Puma
940
1160
 
941
1161
  # Set the timeout for worker shutdown.
942
1162
  #
1163
+ # The default is 30 seconds.
1164
+ #
943
1165
  # @note Cluster mode only.
1166
+ #
1167
+ # @example
1168
+ # worker_shutdown_timeout 90
1169
+ #
944
1170
  # @see Puma::Cluster::Worker#term
945
1171
  #
946
1172
  def worker_shutdown_timeout(timeout)
@@ -956,22 +1182,26 @@ module Puma
956
1182
  # 2. **:oldest** - the oldest workers (i.e. the workers that were started
957
1183
  # the longest time ago) will be culled.
958
1184
  #
1185
+ # The default is +:youngest+.
1186
+ #
959
1187
  # @note Cluster mode only.
1188
+ #
960
1189
  # @example
961
1190
  # worker_culling_strategy :oldest
1191
+ #
962
1192
  # @see Puma::Cluster#cull_workers
963
1193
  #
964
1194
  def worker_culling_strategy(strategy)
965
- stategy = strategy.to_sym
1195
+ strategy = strategy.to_sym
966
1196
 
967
1197
  if ![:youngest, :oldest].include?(strategy)
968
- raise "Invalid value for worker_culling_strategy - #{stategy}"
1198
+ raise "Invalid value for worker_culling_strategy - #{strategy}"
969
1199
  end
970
1200
 
971
1201
  @options[:worker_culling_strategy] = strategy
972
1202
  end
973
1203
 
974
- # When set to true (the default), workers accept all requests
1204
+ # When set to true, workers accept all requests
975
1205
  # and queue them before passing them to the handlers.
976
1206
  # When set to false, each worker process accepts exactly as
977
1207
  # many requests as it is configured to simultaneously handle.
@@ -984,7 +1214,11 @@ module Puma
984
1214
  # slow clients will occupy a handler thread while the request
985
1215
  # is being sent. A reverse proxy, such as nginx, can handle
986
1216
  # slow clients and queue requests before they reach Puma.
1217
+ #
1218
+ # The default is +true+.
1219
+ #
987
1220
  # @see Puma::Server
1221
+ #
988
1222
  def queue_requests(answer=true)
989
1223
  @options[:queue_requests] = answer
990
1224
  end
@@ -998,14 +1232,22 @@ module Puma
998
1232
  end
999
1233
 
1000
1234
 
1001
- # Attempts to route traffic to less-busy workers by causing them to delay
1002
- # listening on the socket, allowing workers which are not processing any
1235
+ # Maximum delay of worker accept loop.
1236
+ #
1237
+ # Attempts to route traffic to less-busy workers by causing a busy worker to delay
1238
+ # listening on the socket, allowing workers which are not processing as many
1003
1239
  # requests to pick up new requests first.
1004
1240
  #
1005
- # Only works on MRI. For all other interpreters, this setting does nothing.
1241
+ # The default is 0.005 seconds.
1242
+ #
1243
+ # To turn off this feature, set the value to 0.
1244
+ #
1245
+ # @note Cluster mode with >= 2 workers only.
1246
+ #
1247
+ # @note Interpreters with forking support only.
1248
+ #
1006
1249
  # @see Puma::Server#handle_servers
1007
1250
  # @see Puma::ThreadPool#wait_for_less_busy_worker
1008
- # @version 5.0.0
1009
1251
  #
1010
1252
  def wait_for_less_busy_worker(val=0.005)
1011
1253
  @options[:wait_for_less_busy_worker] = val.to_f
@@ -1018,7 +1260,7 @@ module Puma
1018
1260
  #
1019
1261
  # There are 5 possible values:
1020
1262
  #
1021
- # 1. **:socket** (the default) - read the peername from the socket using the
1263
+ # 1. **:socket** - read the peername from the socket using the
1022
1264
  # syscall. This is the normal behavior. If this fails for any reason (e.g.,
1023
1265
  # if the peer disconnects between the connection being accepted and the getpeername
1024
1266
  # system call), Puma will return "0.0.0.0"
@@ -1036,6 +1278,11 @@ module Puma
1036
1278
  # you wish. Because Puma never uses this field anyway, it's format is
1037
1279
  # entirely in your hands.
1038
1280
  #
1281
+ # The default is +:socket+.
1282
+ #
1283
+ # @example
1284
+ # set_remote_address :localhost
1285
+ #
1039
1286
  def set_remote_address(val=:socket)
1040
1287
  case val
1041
1288
  when :socket
@@ -1075,18 +1322,57 @@ module Puma
1075
1322
  # A refork will automatically trigger once after the specified number of requests
1076
1323
  # (default 1000), or pass 0 to disable auto refork.
1077
1324
  #
1325
+ # @note This is experimental.
1078
1326
  # @note Cluster mode only.
1079
- # @version 5.0.0
1080
1327
  #
1081
1328
  def fork_worker(after_requests=1000)
1082
1329
  @options[:fork_worker] = Integer(after_requests)
1083
1330
  end
1084
1331
 
1085
- # The number of requests to attempt inline before sending a client back to
1086
- # the reactor to be subject to normal ordering.
1332
+ # @deprecated Use {#max_keep_alive} instead.
1087
1333
  #
1088
1334
  def max_fast_inline(num_of_requests)
1089
- @options[:max_fast_inline] = Float(num_of_requests)
1335
+ Puma.deprecate_method_change :max_fast_inline, __method__, :max_keep_alive
1336
+ @options[:max_keep_alive] ||= Float(num_of_requests) unless num_of_requests.nil?
1337
+ end
1338
+
1339
+ # The number of requests a keep-alive client can submit before being closed.
1340
+ # Note that some applications (server to server) may benefit from a very high
1341
+ # number or Float::INFINITY.
1342
+ #
1343
+ # The default is 999.
1344
+ #
1345
+ # @example
1346
+ # max_keep_alive 20
1347
+ #
1348
+ def max_keep_alive(num_of_requests)
1349
+ @options[:max_keep_alive] = Float(num_of_requests) unless num_of_requests.nil?
1350
+ end
1351
+
1352
+ # When `true`, keep-alive connections are maintained on inbound requests.
1353
+ # Enabling this setting reduces the number of TCP operations, reducing response
1354
+ # times for connections that can send multiple requests in a single connection.
1355
+ #
1356
+ # When Puma receives more incoming connections than available Puma threads,
1357
+ # enabling the keep-alive behavior may result in processing requests out-of-order,
1358
+ # increasing overall response time variance. Increased response time variance
1359
+ # means that the overall average of response times might not change, but more
1360
+ # outliers will exist. Those long-tail outliers may significantly affect response
1361
+ # times for some processed requests.
1362
+ #
1363
+ # When `false`, Puma closes the connection after each request, requiring the
1364
+ # client to open a new request. Disabling this setting guarantees that requests
1365
+ # will be processed in the order they are fully received, decreasing response
1366
+ # variance and eliminating long-tail outliers caused by keep-alive behavior.
1367
+ # The trade-off is that the number of TCP operations required will increase.
1368
+ #
1369
+ # The default is +true+.
1370
+ #
1371
+ # @example
1372
+ # enable_keep_alives false
1373
+ #
1374
+ def enable_keep_alives(enabled=true)
1375
+ @options[:enable_keep_alives] = enabled
1090
1376
  end
1091
1377
 
1092
1378
  # Specify the backend for the IO selector.
@@ -1102,12 +1388,20 @@ module Puma
1102
1388
  #
1103
1389
  # The default is +:auto+.
1104
1390
  #
1105
- # @see https://github.com/socketry/nio4r/blob/master/lib/nio/selector.rb
1391
+ # @see https://github.com/socketry/nio4r/blob/main/lib/nio/selector.rb
1106
1392
  #
1107
1393
  def io_selector_backend(backend)
1108
1394
  @options[:io_selector_backend] = backend.to_sym
1109
1395
  end
1110
1396
 
1397
+ # Ensures +STDOUT+ and +STDERR+ is immediately flushed to the underlying
1398
+ # operating system and is not buffered internally
1399
+ #
1400
+ # The default is +true+.
1401
+ #
1402
+ # @example
1403
+ # mutate_stdout_and_stderr_to_sync_on_write false
1404
+ #
1111
1405
  def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
1112
1406
  @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
1113
1407
  end
@@ -1119,8 +1413,12 @@ module Puma
1119
1413
  #
1120
1414
  # When no Content-Length http header is present, it is compared against the
1121
1415
  # size of the body of the request.
1122
- #
1123
- # The default value for http_content_length_limit is nil.
1416
+ #
1417
+ # The default is +nil+.
1418
+ #
1419
+ # @example
1420
+ # http_content_length_limit 2_000_000_000
1421
+ #
1124
1422
  def http_content_length_limit(limit)
1125
1423
  @options[:http_content_length_limit] = limit
1126
1424
  end
@@ -1161,6 +1459,7 @@ module Puma
1161
1459
 
1162
1460
  # To avoid adding cert_pem and key_pem as URI params, we store them on the
1163
1461
  # options[:store] from where Puma binder knows how to find and extract them.
1462
+ #
1164
1463
  def add_pem_values_to_options_store(opts)
1165
1464
  return if defined?(JRUBY_VERSION)
1166
1465
 
@@ -1177,30 +1476,21 @@ module Puma
1177
1476
  end
1178
1477
  end
1179
1478
 
1180
- def process_hook(options_key, key, block, meth)
1479
+ def process_hook(options_key, key, block, cluster_only: false)
1480
+ raise ArgumentError, "expected #{options_key} to be given a block" unless block
1481
+
1482
+ @config.hooks[options_key] = true
1483
+
1181
1484
  @options[options_key] ||= []
1182
- if ON_WORKER_KEY.include? key.class
1183
- @options[options_key] << [block, key.to_sym]
1485
+ hook_options = { block: block, cluster_only: cluster_only }
1486
+ hook_options[:id] = if ON_WORKER_KEY.include?(key.class)
1487
+ key.to_sym
1184
1488
  elsif key.nil?
1185
- @options[options_key] << block
1489
+ nil
1186
1490
  else
1187
- raise "'#{meth}' key must be String or Symbol"
1188
- end
1189
- end
1190
-
1191
- def warn_if_in_single_mode(hook_name)
1192
- return if @options[:silence_fork_callback_warning]
1193
- # user_options (CLI) have precedence over config file
1194
- workers_val = @config.options.user_options[:workers] || @options[:workers] ||
1195
- @config.puma_default_options[:workers] || 0
1196
- if workers_val == 0
1197
- log_string =
1198
- "Warning: You specified code to run in a `#{hook_name}` block, " \
1199
- "but Puma is not configured to run in cluster mode (worker count > 0 ), " \
1200
- "so your `#{hook_name}` block did not run"
1201
-
1202
- LogWriter.stdio.log(log_string)
1491
+ raise "'#{options_key}' key must be String or Symbol"
1203
1492
  end
1493
+ @options[options_key] << hook_options
1204
1494
  end
1205
1495
  end
1206
1496
  end