puma 6.6.0 → 8.0.2

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +309 -5
  3. data/README.md +41 -42
  4. data/docs/5.0-Upgrade.md +98 -0
  5. data/docs/6.0-Upgrade.md +56 -0
  6. data/docs/7.0-Upgrade.md +52 -0
  7. data/docs/8.0-Upgrade.md +100 -0
  8. data/docs/deployment.md +58 -23
  9. data/docs/fork_worker.md +5 -5
  10. data/docs/grpc.md +62 -0
  11. data/docs/images/favicon.svg +1 -0
  12. data/docs/images/running-puma.svg +1 -0
  13. data/docs/images/standard-logo.svg +1 -0
  14. data/docs/jungle/README.md +1 -1
  15. data/docs/kubernetes.md +11 -16
  16. data/docs/plugins.md +2 -2
  17. data/docs/restart.md +2 -2
  18. data/docs/signals.md +21 -21
  19. data/docs/stats.md +4 -3
  20. data/docs/systemd.md +4 -4
  21. data/ext/puma_http11/extconf.rb +2 -17
  22. data/ext/puma_http11/http11_parser.java.rl +51 -65
  23. data/ext/puma_http11/mini_ssl.c +18 -8
  24. data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
  25. data/ext/puma_http11/org/jruby/puma/Http11.java +174 -102
  26. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +71 -85
  27. data/ext/puma_http11/puma_http11.c +122 -118
  28. data/lib/puma/app/status.rb +10 -2
  29. data/lib/puma/binder.rb +12 -10
  30. data/lib/puma/cli.rb +4 -6
  31. data/lib/puma/client.rb +205 -131
  32. data/lib/puma/client_env.rb +171 -0
  33. data/lib/puma/cluster/worker.rb +17 -17
  34. data/lib/puma/cluster/worker_handle.rb +38 -7
  35. data/lib/puma/cluster.rb +44 -30
  36. data/lib/puma/cluster_accept_loop_delay.rb +91 -0
  37. data/lib/puma/commonlogger.rb +3 -3
  38. data/lib/puma/configuration.rb +173 -58
  39. data/lib/puma/const.rb +11 -11
  40. data/lib/puma/control_cli.rb +7 -3
  41. data/lib/puma/detect.rb +13 -0
  42. data/lib/puma/dsl.rb +225 -108
  43. data/lib/puma/error_logger.rb +3 -1
  44. data/lib/puma/events.rb +25 -10
  45. data/lib/puma/io_buffer.rb +8 -4
  46. data/lib/puma/launcher/bundle_pruner.rb +3 -5
  47. data/lib/puma/launcher.rb +57 -53
  48. data/lib/puma/log_writer.rb +8 -2
  49. data/lib/puma/minissl.rb +0 -1
  50. data/lib/puma/plugin/systemd.rb +3 -3
  51. data/lib/puma/rack/urlmap.rb +1 -1
  52. data/lib/puma/reactor.rb +19 -13
  53. data/lib/puma/{request.rb → response.rb} +56 -212
  54. data/lib/puma/runner.rb +9 -18
  55. data/lib/puma/server.rb +182 -97
  56. data/lib/puma/server_plugin_control.rb +32 -0
  57. data/lib/puma/single.rb +7 -4
  58. data/lib/puma/state_file.rb +3 -2
  59. data/lib/puma/thread_pool.rb +170 -99
  60. data/lib/puma/util.rb +0 -7
  61. data/lib/puma.rb +10 -0
  62. data/lib/rack/handler/puma.rb +3 -3
  63. data/tools/Dockerfile +15 -5
  64. metadata +19 -7
  65. 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,11 +43,11 @@ 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 |
50
- # | after_refork | :after_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 |
51
51
  #
52
52
  class DSL
53
53
  ON_WORKER_KEY = [String, Symbol].freeze
@@ -155,7 +155,7 @@ module Puma
155
155
  end
156
156
 
157
157
  def default_host
158
- @options[:default_host] || Configuration::DEFAULTS[:tcp_host]
158
+ @options[:default_host] || Configuration.default_tcp_host
159
159
  end
160
160
 
161
161
  def inject(&blk)
@@ -216,6 +216,8 @@ module Puma
216
216
  # activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
217
217
  # @example
218
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}
219
221
  #
220
222
  def activate_control_app(url="auto", opts={})
221
223
  if url == "auto"
@@ -240,6 +242,7 @@ module Puma
240
242
 
241
243
  @options[:control_auth_token] = auth_token
242
244
  @options[:control_url_umask] = opts[:umask] if opts[:umask]
245
+ @options[:control_data_only] = opts[:data_only] if opts[:data_only]
243
246
  end
244
247
 
245
248
  # Load additional configuration from a file.
@@ -257,7 +260,8 @@ module Puma
257
260
  # accepted protocols. Multiple urls can be bound to, calling +bind+ does
258
261
  # not overwrite previous bindings.
259
262
  #
260
- # The default is "tcp://0.0.0.0:9292".
263
+ # The default is "tcp://[::]:9292" when IPv6 interfaces are available,
264
+ # otherwise "tcp://0.0.0.0:9292".
261
265
  #
262
266
  # You can use query parameters within the url to specify options:
263
267
  #
@@ -276,7 +280,7 @@ module Puma
276
280
  # @example SSL cert for mutual TLS (mTLS)
277
281
  # bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem&ca=ca.pem&verify_mode=force_peer'
278
282
  # @example Disable optimization for low latency
279
- # bind 'tcp://0.0.0.0:9292?low_latency=false'
283
+ # bind 'tcp://[::]:9292?low_latency=false'
280
284
  # @example Socket permissions
281
285
  # bind 'unix:///var/run/puma.sock?umask=0111'
282
286
  #
@@ -346,7 +350,7 @@ module Puma
346
350
 
347
351
  # Define how long persistent connections can be idle before Puma closes them.
348
352
  #
349
- # The default is 20 seconds.
353
+ # The default is 65 seconds.
350
354
  #
351
355
  # @example
352
356
  # persistent_timeout 30
@@ -370,18 +374,21 @@ module Puma
370
374
  @options[:idle_timeout] = Integer(seconds)
371
375
  end
372
376
 
373
- # Work around leaky apps that leave garbage in Thread locals
374
- # across requests.
377
+ # Use a clean fiber per request which ensures a clean slate for fiber
378
+ # locals and fiber storage. Also provides a cleaner backtrace with less
379
+ # Puma internal stack frames.
375
380
  #
376
381
  # The default is +false+.
377
382
  #
378
383
  # @example
379
- # clean_thread_locals
384
+ # fiber_per_request
380
385
  #
381
- def clean_thread_locals(which=true)
382
- @options[:clean_thread_locals] = which
386
+ def fiber_per_request(which=true)
387
+ @options[:fiber_per_request] = which
383
388
  end
384
389
 
390
+ alias clean_thread_locals fiber_per_request
391
+
385
392
  # When shutting down, drain the accept socket of pending connections and
386
393
  # process them. This loops over the accept socket until there are no more
387
394
  # read events and then stops looking and waits for the requests to finish.
@@ -434,14 +441,18 @@ module Puma
434
441
  # This can be called multiple times to add code each time.
435
442
  #
436
443
  # @example
437
- # on_restart do
444
+ # before_restart do
438
445
  # puts 'On restart...'
439
446
  # end
440
447
  #
441
- def on_restart(&block)
442
- process_hook :on_restart, nil, block, 'on_restart'
448
+ def before_restart(&block)
449
+ Puma.deprecate_method_change :on_restart, __callee__, __method__
450
+
451
+ process_hook :before_restart, nil, block
443
452
  end
444
453
 
454
+ alias_method :on_restart, :before_restart
455
+
445
456
  # Command to use to restart Puma. This should be just how to
446
457
  # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
447
458
  # to Puma, as those are the same as the original process.
@@ -585,6 +596,29 @@ module Puma
585
596
  @options[:max_threads] = max
586
597
  end
587
598
 
599
+ # Configure the max number of IO threads.
600
+ #
601
+ # When request handlers know the current requests will no longer use a significant amount
602
+ # of CPU, they can mark the current request as IO bound using <tt>env["puma.mark_as_io_bound"]</tt>.
603
+ #
604
+ # Threads marked as IO bound are allowed to go over the max thread limit.
605
+ #
606
+ # @example
607
+ # threads 5
608
+ # max_io_threads 5
609
+ #
610
+ # The above example allows for 5 regular threads and 5 IO threads to process requests concurrently.
611
+ # Any IO thread over the limit is counted as a regular thread, hence the above configuration also
612
+ # allows for 3 regular threads and 7 IO threads for example.
613
+ def max_io_threads(max)
614
+ max = Integer(max)
615
+ if max < 0
616
+ raise "The maximum number of IO threads (#{max}) must be a positive number"
617
+ end
618
+
619
+ @options[:max_io_threads] = max
620
+ end
621
+
588
622
  # Instead of using +bind+ and manually constructing a URI like:
589
623
  #
590
624
  # bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
@@ -649,32 +683,37 @@ module Puma
649
683
  @options[:state] = path.to_s
650
684
  end
651
685
 
652
- # Use +permission+ to restrict permissions for the state file.
686
+ # Use +permission+ to restrict permissions for the state file. By convention,
687
+ # +permission+ is an octal number (e.g. `0640` or `0o640`).
653
688
  #
654
689
  # @example
655
690
  # state_permission 0600
656
691
  #
657
- # @version 5.0.0
658
- #
659
692
  def state_permission(permission)
660
693
  @options[:state_permission] = permission
661
694
  end
662
695
 
663
- # How many worker processes to run. Typically this is set to
664
- # the number of available cores.
696
+ # How many worker processes to run. Typically this is set to the number of
697
+ # available cores.
665
698
  #
666
699
  # The default is the value of the environment variable +WEB_CONCURRENCY+ if
667
- # set, otherwise 0.
700
+ # set, otherwise 0. Passing +:auto+ will set the value to
701
+ # +Concurrent.available_processor_count+ (requires the concurrent-ruby gem).
702
+ # On some platforms (e.g. under CPU quotas) this may be fractional, and Puma
703
+ # will round down. If it rounds down to 0, Puma will run in single mode and
704
+ # cluster-only hooks like +before_worker_boot+ will not execute.
705
+ # If you rely on cluster-only hooks, set an explicit worker count.
668
706
  #
669
- # @note Cluster mode only.
707
+ # A value of 0 or nil means run in single mode.
670
708
  #
671
709
  # @example
672
710
  # workers 2
711
+ # workers :auto
673
712
  #
674
713
  # @see Puma::Cluster
675
714
  #
676
715
  def workers(count)
677
- @options[:workers] = count.to_i
716
+ @options[:workers] = count.nil? ? 0 : @config.send(:parse_workers, count)
678
717
  end
679
718
 
680
719
  # Disable warning message when running in cluster mode with a single worker.
@@ -712,6 +751,44 @@ module Puma
712
751
  @options[:silence_fork_callback_warning] = true
713
752
  end
714
753
 
754
+ # Code to run only in single mode.
755
+ # Runs after all config files are loaded.
756
+ #
757
+ # This can be called multiple times.
758
+ #
759
+ # @note Single mode only.
760
+ #
761
+ # @example
762
+ # single do
763
+ # silence_fork_callback_warning
764
+ # end
765
+ #
766
+ def single(&block)
767
+ raise ArgumentError, "A block must be provided to `single`" unless block
768
+
769
+ @options[:single] ||= []
770
+ @options[:single] << block
771
+ end
772
+
773
+ # Code to run only in cluster mode.
774
+ # Runs after all config files are loaded.
775
+ #
776
+ # This can be called multiple times.
777
+ #
778
+ # @note Cluster mode only.
779
+ #
780
+ # @example
781
+ # cluster do
782
+ # prune_bundler
783
+ # end
784
+ #
785
+ def cluster(&block)
786
+ raise ArgumentError, "A block must be provided to `cluster`" unless block
787
+
788
+ @options[:cluster] ||= []
789
+ @options[:cluster] << block
790
+ end
791
+
715
792
  # Code to run immediately before master process
716
793
  # forks workers (once on boot). These hooks can block if necessary
717
794
  # to wait for background operations unknown to Puma to finish before
@@ -729,9 +806,7 @@ module Puma
729
806
  # end
730
807
  #
731
808
  def before_fork(&block)
732
- warn_if_in_single_mode('before_fork')
733
-
734
- process_hook :before_fork, nil, block, 'before_fork'
809
+ process_hook :before_fork, nil, block, cluster_only: true
735
810
  end
736
811
 
737
812
  # Code to run in a worker when it boots to setup
@@ -742,16 +817,18 @@ module Puma
742
817
  # @note Cluster mode only.
743
818
  #
744
819
  # @example
745
- # on_worker_boot do
820
+ # before_worker_boot do
746
821
  # puts 'Before worker boot...'
747
822
  # end
748
823
  #
749
- def on_worker_boot(key = nil, &block)
750
- warn_if_in_single_mode('on_worker_boot')
824
+ def before_worker_boot(key = nil, &block)
825
+ Puma.deprecate_method_change :on_worker_boot, __callee__, __method__
751
826
 
752
- process_hook :before_worker_boot, key, block, 'on_worker_boot'
827
+ process_hook :before_worker_boot, key, block, cluster_only: true
753
828
  end
754
829
 
830
+ alias_method :on_worker_boot, :before_worker_boot
831
+
755
832
  # Code to run immediately before a worker shuts
756
833
  # down (after it has finished processing HTTP requests). The worker's
757
834
  # index is passed as an argument. These hooks
@@ -763,16 +840,18 @@ module Puma
763
840
  # @note Cluster mode only.
764
841
  #
765
842
  # @example
766
- # on_worker_shutdown do
843
+ # before_worker_shutdown do
767
844
  # puts 'On worker shutdown...'
768
845
  # end
769
846
  #
770
- def on_worker_shutdown(key = nil, &block)
771
- warn_if_in_single_mode('on_worker_shutdown')
847
+ def before_worker_shutdown(key = nil, &block)
848
+ Puma.deprecate_method_change :on_worker_shutdown, __callee__, __method__
772
849
 
773
- process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
850
+ process_hook :before_worker_shutdown, key, block, cluster_only: true
774
851
  end
775
852
 
853
+ alias_method :on_worker_shutdown, :before_worker_shutdown
854
+
776
855
  # Code to run in the master right before a worker is started. The worker's
777
856
  # index is passed as an argument.
778
857
  #
@@ -781,16 +860,18 @@ module Puma
781
860
  # @note Cluster mode only.
782
861
  #
783
862
  # @example
784
- # on_worker_fork do
863
+ # before_worker_fork do
785
864
  # puts 'Before worker fork...'
786
865
  # end
787
866
  #
788
- def on_worker_fork(&block)
789
- warn_if_in_single_mode('on_worker_fork')
867
+ def before_worker_fork(&block)
868
+ Puma.deprecate_method_change :on_worker_fork, __callee__, __method__
790
869
 
791
- process_hook :before_worker_fork, nil, block, 'on_worker_fork'
870
+ process_hook :before_worker_fork, nil, block, cluster_only: true
792
871
  end
793
872
 
873
+ alias_method :on_worker_fork, :before_worker_fork
874
+
794
875
  # Code to run in the master after a worker has been started. The worker's
795
876
  # index is passed as an argument.
796
877
  #
@@ -804,34 +885,53 @@ module Puma
804
885
  # end
805
886
  #
806
887
  def after_worker_fork(&block)
807
- warn_if_in_single_mode('after_worker_fork')
808
-
809
- process_hook :after_worker_fork, nil, block, 'after_worker_fork'
888
+ process_hook :after_worker_fork, nil, block, cluster_only: true
810
889
  end
811
890
 
812
891
  alias_method :after_worker_boot, :after_worker_fork
813
892
 
814
- # Code to run after puma is booted (works for both: single and clustered)
893
+ # Code to run in the master right after a worker has stopped. The worker's
894
+ # index and Process::Status are passed as arguments.
895
+ #
896
+ # @note Cluster mode only.
815
897
  #
816
898
  # @example
817
- # on_booted do
899
+ # after_worker_shutdown do |worker_handle|
900
+ # puts 'Worker crashed' unless worker_handle.process_status.success?
901
+ # end
902
+ #
903
+ def after_worker_shutdown(&block)
904
+ process_hook :after_worker_shutdown, nil, block, cluster_only: true
905
+ end
906
+
907
+ # Code to run after puma is booted (works for both single and cluster modes).
908
+ #
909
+ # @example
910
+ # after_booted do
818
911
  # puts 'After booting...'
819
912
  # end
820
913
  #
821
- def on_booted(&block)
822
- @config.options[:events].on_booted(&block)
914
+ def after_booted(&block)
915
+ Puma.deprecate_method_change :on_booted, __callee__, __method__
916
+
917
+ @config.events.after_booted(&block)
823
918
  end
824
919
 
920
+ alias_method :on_booted, :after_booted
921
+
825
922
  # Code to run after puma is stopped (works for both: single and clustered)
826
923
  #
827
924
  # @example
828
- # on_stopped do
925
+ # after_stopped do
829
926
  # puts 'After stopping...'
830
927
  # end
831
928
  #
832
- def on_stopped(&block)
833
- @config.options[:events].on_stopped(&block)
929
+ def after_stopped(&block)
930
+ Puma.deprecate_method_change :on_stopped, __callee__, __method__
931
+
932
+ @config.events.after_stopped(&block)
834
933
  end
934
+ alias_method :on_stopped, :after_stopped
835
935
 
836
936
  # When `fork_worker` is enabled, code to run in Worker 0
837
937
  # before all other workers are re-forked from this process,
@@ -847,25 +947,27 @@ module Puma
847
947
  # @note Cluster mode with `fork_worker` enabled only.
848
948
  #
849
949
  # @example
850
- # on_refork do
950
+ # before_refork do
851
951
  # 3.times {GC.start}
852
952
  # end
853
953
  #
854
954
  # @version 5.0.0
855
955
  #
856
- def on_refork(key = nil, &block)
857
- warn_if_in_single_mode('on_refork')
956
+ def before_refork(key = nil, &block)
957
+ Puma.deprecate_method_change :on_refork, __callee__, __method__
858
958
 
859
- process_hook :before_refork, key, block, 'on_refork'
959
+ process_hook :before_refork, key, block, cluster_only: true
860
960
  end
861
961
 
962
+ alias_method :on_refork, :before_refork
963
+
862
964
  # When `fork_worker` is enabled, code to run in Worker 0
863
965
  # after all other workers are re-forked from this process,
864
966
  # after the server has temporarily stopped serving requests
865
967
  # (once per complete refork cycle).
866
968
  #
867
969
  # This can be used to re-open any connections to remote servers
868
- # (database, Redis, ...) that were closed via on_refork.
970
+ # (database, Redis, ...) that were closed via before_refork.
869
971
  #
870
972
  # This can be called multiple times to add several hooks.
871
973
  #
@@ -877,7 +979,7 @@ module Puma
877
979
  # end
878
980
  #
879
981
  def after_refork(key = nil, &block)
880
- process_hook :after_refork, key, block, 'after_refork'
982
+ process_hook :after_refork, key, block
881
983
  end
882
984
 
883
985
  # Provide a block to be executed just before a thread is added to the thread
@@ -893,14 +995,18 @@ module Puma
893
995
  # This can be called multiple times to add several hooks.
894
996
  #
895
997
  # @example
896
- # on_thread_start do
998
+ # before_thread_start do
897
999
  # puts 'On thread start...'
898
1000
  # end
899
1001
  #
900
- def on_thread_start(&block)
901
- process_hook :before_thread_start, nil, block, 'on_thread_start'
1002
+ def before_thread_start(&block)
1003
+ Puma.deprecate_method_change :on_thread_start, __callee__, __method__
1004
+
1005
+ process_hook :before_thread_start, nil, block
902
1006
  end
903
1007
 
1008
+ alias_method :on_thread_start, :before_thread_start
1009
+
904
1010
  # Provide a block to be executed after a thread is trimmed from the thread
905
1011
  # pool. Be careful: while this block executes, Puma's main loop is
906
1012
  # blocked, so no new requests will be picked up.
@@ -917,14 +1023,18 @@ module Puma
917
1023
  # This can be called multiple times to add several hooks.
918
1024
  #
919
1025
  # @example
920
- # on_thread_exit do
1026
+ # before_thread_exit do
921
1027
  # puts 'On thread exit...'
922
1028
  # end
923
1029
  #
924
- def on_thread_exit(&block)
925
- process_hook :before_thread_exit, nil, block, 'on_thread_exit'
1030
+ def before_thread_exit(&block)
1031
+ Puma.deprecate_method_change :on_thread_exit, __callee__, __method__
1032
+
1033
+ process_hook :before_thread_exit, nil, block
926
1034
  end
927
1035
 
1036
+ alias_method :on_thread_exit, :before_thread_exit
1037
+
928
1038
  # Code to run out-of-band when the worker is idle.
929
1039
  # These hooks run immediately after a request has finished
930
1040
  # processing and there are no busy threads on the worker.
@@ -936,7 +1046,7 @@ module Puma
936
1046
  # This can be called multiple times to add several hooks.
937
1047
  #
938
1048
  def out_of_band(&block)
939
- process_hook :out_of_band, nil, block, 'out_of_band'
1049
+ process_hook :out_of_band, nil, block
940
1050
  end
941
1051
 
942
1052
  # The directory to operate out of.
@@ -950,12 +1060,13 @@ module Puma
950
1060
  @options[:directory] = dir.to_s
951
1061
  end
952
1062
 
953
- # Preload the application before starting the workers; this conflicts with
954
- # phased restart feature.
1063
+ # Preload the application before forking the workers; this conflicts with
1064
+ # the phased restart feature.
955
1065
  #
956
1066
  # The default is +true+ if your app uses more than 1 worker.
957
1067
  #
958
1068
  # @note Cluster mode only.
1069
+ # @note When using `fork_worker`, this only applies to worker 0.
959
1070
  #
960
1071
  # @example
961
1072
  # preload_app!
@@ -991,6 +1102,7 @@ module Puma
991
1102
  # new Bundler context and thus can float around as the release
992
1103
  # dictates.
993
1104
  #
1105
+ # @note Cluster mode only.
994
1106
  # @note This is incompatible with +preload_app!+.
995
1107
  # @note This is only supported for RubyGems 2.2+
996
1108
  #
@@ -1096,7 +1208,7 @@ module Puma
1096
1208
 
1097
1209
  # Change the default worker timeout for booting.
1098
1210
  #
1099
- # The default is the value of `worker_timeout`.
1211
+ # The default is 60 seconds.
1100
1212
  #
1101
1213
  # @note Cluster mode only.
1102
1214
  #
@@ -1111,7 +1223,7 @@ module Puma
1111
1223
 
1112
1224
  # Set the timeout for worker shutdown.
1113
1225
  #
1114
- # The default is 60 seconds.
1226
+ # The default is 30 seconds.
1115
1227
  #
1116
1228
  # @note Cluster mode only.
1117
1229
  #
@@ -1143,10 +1255,10 @@ module Puma
1143
1255
  # @see Puma::Cluster#cull_workers
1144
1256
  #
1145
1257
  def worker_culling_strategy(strategy)
1146
- stategy = strategy.to_sym
1258
+ strategy = strategy.to_sym
1147
1259
 
1148
1260
  if ![:youngest, :oldest].include?(strategy)
1149
- raise "Invalid value for worker_culling_strategy - #{stategy}"
1261
+ raise "Invalid value for worker_culling_strategy - #{strategy}"
1150
1262
  end
1151
1263
 
1152
1264
  @options[:worker_culling_strategy] = strategy
@@ -1178,24 +1290,31 @@ module Puma
1178
1290
  # threads will be written to $stdout. This can help figure
1179
1291
  # out why shutdown is hanging.
1180
1292
  #
1181
- def shutdown_debug(val=true)
1182
- @options[:shutdown_debug] = val
1293
+ # If `on_force` is true, the backtraces will be written only
1294
+ # when the shutdown is forced i.e. not graceful.
1295
+ #
1296
+ # @see force_shutdown_after
1297
+ def shutdown_debug(val = true, on_force: false)
1298
+ @options[:shutdown_debug] = val && on_force ? :on_force : val
1183
1299
  end
1184
1300
 
1185
-
1186
- # Attempts to route traffic to less-busy workers by causing them to delay
1187
- # listening on the socket, allowing workers which are not processing any
1301
+ # Maximum delay of worker accept loop.
1302
+ #
1303
+ # Attempts to route traffic to less-busy workers by causing a busy worker to delay
1304
+ # listening on the socket, allowing workers which are not processing as many
1188
1305
  # requests to pick up new requests first.
1189
1306
  #
1190
1307
  # The default is 0.005 seconds.
1191
1308
  #
1192
- # Only works on MRI. For all other interpreters, this setting does nothing.
1309
+ # To turn off this feature, set the value to 0.
1310
+ #
1311
+ # @note Cluster mode with >= 2 workers only.
1312
+ #
1313
+ # @note Interpreters with forking support only.
1193
1314
  #
1194
1315
  # @see Puma::Server#handle_servers
1195
1316
  # @see Puma::ThreadPool#wait_for_less_busy_worker
1196
1317
  #
1197
- # @version 5.0.0
1198
- #
1199
1318
  def wait_for_less_busy_worker(val=0.005)
1200
1319
  @options[:wait_for_less_busy_worker] = val.to_f
1201
1320
  end
@@ -1269,24 +1388,31 @@ module Puma
1269
1388
  # A refork will automatically trigger once after the specified number of requests
1270
1389
  # (default 1000), or pass 0 to disable auto refork.
1271
1390
  #
1391
+ # @note This is experimental.
1272
1392
  # @note Cluster mode only.
1273
1393
  #
1274
- # @version 5.0.0
1275
- #
1276
1394
  def fork_worker(after_requests=1000)
1277
1395
  @options[:fork_worker] = Integer(after_requests)
1278
1396
  end
1279
1397
 
1280
- # The number of requests to attempt inline before sending a client back to
1281
- # the reactor to be subject to normal ordering.
1398
+ # @deprecated Use {#max_keep_alive} instead.
1399
+ #
1400
+ def max_fast_inline(num_of_requests)
1401
+ Puma.deprecate_method_change :max_fast_inline, __method__, :max_keep_alive
1402
+ @options[:max_keep_alive] ||= Float(num_of_requests) unless num_of_requests.nil?
1403
+ end
1404
+
1405
+ # The number of requests a keep-alive client can submit before being closed.
1406
+ # Note that some applications (server to server) may benefit from a very high
1407
+ # number or Float::INFINITY.
1282
1408
  #
1283
- # The default is 10.
1409
+ # The default is 999.
1284
1410
  #
1285
1411
  # @example
1286
- # max_fast_inline 20
1412
+ # max_keep_alive 20
1287
1413
  #
1288
- def max_fast_inline(num_of_requests)
1289
- @options[:max_fast_inline] = Float(num_of_requests)
1414
+ def max_keep_alive(num_of_requests)
1415
+ @options[:max_keep_alive] = Float(num_of_requests) unless num_of_requests.nil?
1290
1416
  end
1291
1417
 
1292
1418
  # When `true`, keep-alive connections are maintained on inbound requests.
@@ -1328,7 +1454,7 @@ module Puma
1328
1454
  #
1329
1455
  # The default is +:auto+.
1330
1456
  #
1331
- # @see https://github.com/socketry/nio4r/blob/master/lib/nio/selector.rb
1457
+ # @see https://github.com/socketry/nio4r/blob/main/lib/nio/selector.rb
1332
1458
  #
1333
1459
  def io_selector_backend(backend)
1334
1460
  @options[:io_selector_backend] = backend.to_sym
@@ -1416,30 +1542,21 @@ module Puma
1416
1542
  end
1417
1543
  end
1418
1544
 
1419
- def process_hook(options_key, key, block, meth)
1545
+ def process_hook(options_key, key, block, cluster_only: false)
1546
+ raise ArgumentError, "expected #{options_key} to be given a block" unless block
1547
+
1548
+ @config.hooks[options_key] = true
1549
+
1420
1550
  @options[options_key] ||= []
1421
- if ON_WORKER_KEY.include? key.class
1422
- @options[options_key] << [block, key.to_sym]
1551
+ hook_options = { block: block, cluster_only: cluster_only }
1552
+ hook_options[:id] = if ON_WORKER_KEY.include?(key.class)
1553
+ key.to_sym
1423
1554
  elsif key.nil?
1424
- @options[options_key] << block
1555
+ nil
1425
1556
  else
1426
- raise "'#{meth}' key must be String or Symbol"
1427
- end
1428
- end
1429
-
1430
- def warn_if_in_single_mode(hook_name)
1431
- return if @options[:silence_fork_callback_warning]
1432
- # user_options (CLI) have precedence over config file
1433
- workers_val = @config.options.user_options[:workers] || @options[:workers] ||
1434
- @config.puma_default_options[:workers] || 0
1435
- if workers_val == 0
1436
- log_string =
1437
- "Warning: You specified code to run in a `#{hook_name}` block, " \
1438
- "but Puma is not configured to run in cluster mode (worker count > 0), " \
1439
- "so your `#{hook_name}` block will not run."
1440
-
1441
- LogWriter.stdio.log(log_string)
1557
+ raise "'#{options_key}' key must be String or Symbol"
1442
1558
  end
1559
+ @options[options_key] << hook_options
1443
1560
  end
1444
1561
  end
1445
1562
  end
@@ -78,10 +78,12 @@ module Puma
78
78
  def request_title(req)
79
79
  env = req.env
80
80
 
81
+ query_string = env[QUERY_STRING]
82
+
81
83
  REQUEST_FORMAT % [
82
84
  env[REQUEST_METHOD],
83
85
  env[REQUEST_PATH] || env[PATH_INFO],
84
- env[QUERY_STRING] || "",
86
+ query_string.nil? || query_string.empty? ? "" : "?#{query_string}",
85
87
  env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-"
86
88
  ]
87
89
  end