puma 6.6.1-java → 7.1.0-java

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +153 -4
  3. data/README.md +17 -25
  4. data/docs/fork_worker.md +5 -5
  5. data/docs/kubernetes.md +8 -6
  6. data/docs/restart.md +2 -2
  7. data/docs/signals.md +9 -9
  8. data/docs/stats.md +3 -2
  9. data/ext/puma_http11/extconf.rb +2 -17
  10. data/ext/puma_http11/mini_ssl.c +18 -8
  11. data/ext/puma_http11/org/jruby/puma/Http11.java +9 -1
  12. data/ext/puma_http11/puma_http11.c +23 -11
  13. data/lib/puma/binder.rb +10 -8
  14. data/lib/puma/cli.rb +3 -5
  15. data/lib/puma/client.rb +52 -56
  16. data/lib/puma/cluster/worker.rb +9 -10
  17. data/lib/puma/cluster/worker_handle.rb +38 -7
  18. data/lib/puma/cluster.rb +21 -20
  19. data/lib/puma/cluster_accept_loop_delay.rb +91 -0
  20. data/lib/puma/commonlogger.rb +3 -3
  21. data/lib/puma/configuration.rb +89 -43
  22. data/lib/puma/const.rb +9 -10
  23. data/lib/puma/control_cli.rb +6 -2
  24. data/lib/puma/detect.rb +2 -0
  25. data/lib/puma/dsl.rb +133 -85
  26. data/lib/puma/error_logger.rb +3 -1
  27. data/lib/puma/events.rb +25 -10
  28. data/lib/puma/io_buffer.rb +8 -4
  29. data/lib/puma/launcher/bundle_pruner.rb +1 -1
  30. data/lib/puma/launcher.rb +52 -48
  31. data/lib/puma/minissl.rb +0 -1
  32. data/lib/puma/plugin/systemd.rb +3 -3
  33. data/lib/puma/puma_http11.jar +0 -0
  34. data/lib/puma/rack/urlmap.rb +1 -1
  35. data/lib/puma/reactor.rb +19 -4
  36. data/lib/puma/request.rb +33 -24
  37. data/lib/puma/runner.rb +8 -17
  38. data/lib/puma/server.rb +111 -61
  39. data/lib/puma/single.rb +4 -1
  40. data/lib/puma/state_file.rb +3 -2
  41. data/lib/puma/thread_pool.rb +47 -82
  42. data/lib/puma/util.rb +0 -7
  43. data/lib/puma.rb +10 -0
  44. data/lib/rack/handler/puma.rb +2 -2
  45. metadata +6 -4
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
@@ -370,18 +370,21 @@ module Puma
370
370
  @options[:idle_timeout] = Integer(seconds)
371
371
  end
372
372
 
373
- # Work around leaky apps that leave garbage in Thread locals
374
- # across requests.
373
+ # Use a clean fiber per request which ensures a clean slate for fiber
374
+ # locals and fiber storage. Also provides a cleaner backtrace with less
375
+ # Puma internal stack frames.
375
376
  #
376
377
  # The default is +false+.
377
378
  #
378
379
  # @example
379
- # clean_thread_locals
380
+ # fiber_per_request
380
381
  #
381
- def clean_thread_locals(which=true)
382
- @options[:clean_thread_locals] = which
382
+ def fiber_per_request(which=true)
383
+ @options[:fiber_per_request] = which
383
384
  end
384
385
 
386
+ alias clean_thread_locals fiber_per_request
387
+
385
388
  # When shutting down, drain the accept socket of pending connections and
386
389
  # process them. This loops over the accept socket until there are no more
387
390
  # read events and then stops looking and waits for the requests to finish.
@@ -434,14 +437,18 @@ module Puma
434
437
  # This can be called multiple times to add code each time.
435
438
  #
436
439
  # @example
437
- # on_restart do
440
+ # before_restart do
438
441
  # puts 'On restart...'
439
442
  # end
440
443
  #
441
- def on_restart(&block)
442
- process_hook :on_restart, nil, block, 'on_restart'
444
+ def before_restart(&block)
445
+ Puma.deprecate_method_change :on_restart, __callee__, __method__
446
+
447
+ process_hook :before_restart, nil, block
443
448
  end
444
449
 
450
+ alias_method :on_restart, :before_restart
451
+
445
452
  # Command to use to restart Puma. This should be just how to
446
453
  # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
447
454
  # to Puma, as those are the same as the original process.
@@ -649,7 +656,8 @@ module Puma
649
656
  @options[:state] = path.to_s
650
657
  end
651
658
 
652
- # Use +permission+ to restrict permissions for the state file.
659
+ # Use +permission+ to restrict permissions for the state file. By convention,
660
+ # +permission+ is an octal number (e.g. `0640` or `0o640`).
653
661
  #
654
662
  # @example
655
663
  # state_permission 0600
@@ -727,9 +735,7 @@ module Puma
727
735
  # end
728
736
  #
729
737
  def before_fork(&block)
730
- warn_if_in_single_mode('before_fork')
731
-
732
- process_hook :before_fork, nil, block, 'before_fork'
738
+ process_hook :before_fork, nil, block, cluster_only: true
733
739
  end
734
740
 
735
741
  # Code to run in a worker when it boots to setup
@@ -740,16 +746,18 @@ module Puma
740
746
  # @note Cluster mode only.
741
747
  #
742
748
  # @example
743
- # on_worker_boot do
749
+ # before_worker_boot do
744
750
  # puts 'Before worker boot...'
745
751
  # end
746
752
  #
747
- def on_worker_boot(key = nil, &block)
748
- warn_if_in_single_mode('on_worker_boot')
753
+ def before_worker_boot(key = nil, &block)
754
+ Puma.deprecate_method_change :on_worker_boot, __callee__, __method__
749
755
 
750
- process_hook :before_worker_boot, key, block, 'on_worker_boot'
756
+ process_hook :before_worker_boot, key, block, cluster_only: true
751
757
  end
752
758
 
759
+ alias_method :on_worker_boot, :before_worker_boot
760
+
753
761
  # Code to run immediately before a worker shuts
754
762
  # down (after it has finished processing HTTP requests). The worker's
755
763
  # index is passed as an argument. These hooks
@@ -761,16 +769,18 @@ module Puma
761
769
  # @note Cluster mode only.
762
770
  #
763
771
  # @example
764
- # on_worker_shutdown do
772
+ # before_worker_shutdown do
765
773
  # puts 'On worker shutdown...'
766
774
  # end
767
775
  #
768
- def on_worker_shutdown(key = nil, &block)
769
- warn_if_in_single_mode('on_worker_shutdown')
776
+ def before_worker_shutdown(key = nil, &block)
777
+ Puma.deprecate_method_change :on_worker_shutdown, __callee__, __method__
770
778
 
771
- process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
779
+ process_hook :before_worker_shutdown, key, block, cluster_only: true
772
780
  end
773
781
 
782
+ alias_method :on_worker_shutdown, :before_worker_shutdown
783
+
774
784
  # Code to run in the master right before a worker is started. The worker's
775
785
  # index is passed as an argument.
776
786
  #
@@ -779,16 +789,18 @@ module Puma
779
789
  # @note Cluster mode only.
780
790
  #
781
791
  # @example
782
- # on_worker_fork do
792
+ # before_worker_fork do
783
793
  # puts 'Before worker fork...'
784
794
  # end
785
795
  #
786
- def on_worker_fork(&block)
787
- warn_if_in_single_mode('on_worker_fork')
796
+ def before_worker_fork(&block)
797
+ Puma.deprecate_method_change :on_worker_fork, __callee__, __method__
788
798
 
789
- process_hook :before_worker_fork, nil, block, 'on_worker_fork'
799
+ process_hook :before_worker_fork, nil, block, cluster_only: true
790
800
  end
791
801
 
802
+ alias_method :on_worker_fork, :before_worker_fork
803
+
792
804
  # Code to run in the master after a worker has been started. The worker's
793
805
  # index is passed as an argument.
794
806
  #
@@ -802,34 +814,53 @@ module Puma
802
814
  # end
803
815
  #
804
816
  def after_worker_fork(&block)
805
- warn_if_in_single_mode('after_worker_fork')
806
-
807
- process_hook :after_worker_fork, nil, block, 'after_worker_fork'
817
+ process_hook :after_worker_fork, nil, block, cluster_only: true
808
818
  end
809
819
 
810
820
  alias_method :after_worker_boot, :after_worker_fork
811
821
 
822
+ # Code to run in the master right after a worker has stopped. The worker's
823
+ # index and Process::Status are passed as arguments.
824
+ #
825
+ # @note Cluster mode only.
826
+ #
827
+ # @example
828
+ # after_worker_shutdown do |worker_handle|
829
+ # puts 'Worker crashed' unless worker_handle.process_status.success?
830
+ # end
831
+ #
832
+ def after_worker_shutdown(&block)
833
+ process_hook :after_worker_shutdown, nil, block, cluster_only: true
834
+ end
835
+
812
836
  # Code to run after puma is booted (works for both single and cluster modes).
813
837
  #
814
838
  # @example
815
- # on_booted do
839
+ # after_booted do
816
840
  # puts 'After booting...'
817
841
  # end
818
842
  #
819
- def on_booted(&block)
820
- @config.options[:events].on_booted(&block)
843
+ def after_booted(&block)
844
+ Puma.deprecate_method_change :on_booted, __callee__, __method__
845
+
846
+ @config.events.after_booted(&block)
821
847
  end
822
848
 
823
- # Code to run after puma is stopped (works for both single and cluster modes).
849
+ alias_method :on_booted, :after_booted
850
+
851
+ # Code to run after puma is stopped (works for both: single and clustered)
824
852
  #
825
853
  # @example
826
- # on_stopped do
854
+ # after_stopped do
827
855
  # puts 'After stopping...'
828
856
  # end
829
857
  #
830
- def on_stopped(&block)
831
- @config.options[:events].on_stopped(&block)
858
+ def after_stopped(&block)
859
+ Puma.deprecate_method_change :on_stopped, __callee__, __method__
860
+
861
+ @config.events.after_stopped(&block)
832
862
  end
863
+ alias_method :on_stopped, :after_stopped
833
864
 
834
865
  # When `fork_worker` is enabled, code to run in Worker 0
835
866
  # before all other workers are re-forked from this process,
@@ -845,23 +876,27 @@ module Puma
845
876
  # @note Cluster mode with `fork_worker` enabled only.
846
877
  #
847
878
  # @example
848
- # on_refork do
879
+ # before_refork do
849
880
  # 3.times {GC.start}
850
881
  # end
851
882
  #
852
- def on_refork(key = nil, &block)
853
- warn_if_in_single_mode('on_refork')
883
+ # @version 5.0.0
884
+ #
885
+ def before_refork(key = nil, &block)
886
+ Puma.deprecate_method_change :on_refork, __callee__, __method__
854
887
 
855
- process_hook :before_refork, key, block, 'on_refork'
888
+ process_hook :before_refork, key, block, cluster_only: true
856
889
  end
857
890
 
891
+ alias_method :on_refork, :before_refork
892
+
858
893
  # When `fork_worker` is enabled, code to run in Worker 0
859
894
  # after all other workers are re-forked from this process,
860
895
  # after the server has temporarily stopped serving requests
861
896
  # (once per complete refork cycle).
862
897
  #
863
898
  # This can be used to re-open any connections to remote servers
864
- # (database, Redis, ...) that were closed via on_refork.
899
+ # (database, Redis, ...) that were closed via before_refork.
865
900
  #
866
901
  # This can be called multiple times to add several hooks.
867
902
  #
@@ -873,7 +908,7 @@ module Puma
873
908
  # end
874
909
  #
875
910
  def after_refork(key = nil, &block)
876
- process_hook :after_refork, key, block, 'after_refork'
911
+ process_hook :after_refork, key, block
877
912
  end
878
913
 
879
914
  # Provide a block to be executed just before a thread is added to the thread
@@ -889,14 +924,18 @@ module Puma
889
924
  # This can be called multiple times to add several hooks.
890
925
  #
891
926
  # @example
892
- # on_thread_start do
927
+ # before_thread_start do
893
928
  # puts 'On thread start...'
894
929
  # end
895
930
  #
896
- def on_thread_start(&block)
897
- process_hook :before_thread_start, nil, block, 'on_thread_start'
931
+ def before_thread_start(&block)
932
+ Puma.deprecate_method_change :on_thread_start, __callee__, __method__
933
+
934
+ process_hook :before_thread_start, nil, block
898
935
  end
899
936
 
937
+ alias_method :on_thread_start, :before_thread_start
938
+
900
939
  # Provide a block to be executed after a thread is trimmed from the thread
901
940
  # pool. Be careful: while this block executes, Puma's main loop is
902
941
  # blocked, so no new requests will be picked up.
@@ -913,14 +952,18 @@ module Puma
913
952
  # This can be called multiple times to add several hooks.
914
953
  #
915
954
  # @example
916
- # on_thread_exit do
955
+ # before_thread_exit do
917
956
  # puts 'On thread exit...'
918
957
  # end
919
958
  #
920
- def on_thread_exit(&block)
921
- process_hook :before_thread_exit, nil, block, 'on_thread_exit'
959
+ def before_thread_exit(&block)
960
+ Puma.deprecate_method_change :on_thread_exit, __callee__, __method__
961
+
962
+ process_hook :before_thread_exit, nil, block
922
963
  end
923
964
 
965
+ alias_method :on_thread_exit, :before_thread_exit
966
+
924
967
  # Code to run out-of-band when the worker is idle.
925
968
  # These hooks run immediately after a request has finished
926
969
  # processing and there are no busy threads on the worker.
@@ -932,7 +975,7 @@ module Puma
932
975
  # This can be called multiple times to add several hooks.
933
976
  #
934
977
  def out_of_band(&block)
935
- process_hook :out_of_band, nil, block, 'out_of_band'
978
+ process_hook :out_of_band, nil, block
936
979
  end
937
980
 
938
981
  # The directory to operate out of.
@@ -946,8 +989,8 @@ module Puma
946
989
  @options[:directory] = dir.to_s
947
990
  end
948
991
 
949
- # Preload the application before starting the workers; this conflicts with
950
- # phased restart feature.
992
+ # Preload the application before forking the workers; this conflicts with
993
+ # the phased restart feature.
951
994
  #
952
995
  # The default is +true+ if your app uses more than 1 worker.
953
996
  #
@@ -1179,13 +1222,19 @@ module Puma
1179
1222
  end
1180
1223
 
1181
1224
 
1182
- # Attempts to route traffic to less-busy workers by causing them to delay
1183
- # listening on the socket, allowing workers which are not processing any
1225
+ # Maximum delay of worker accept loop.
1226
+ #
1227
+ # Attempts to route traffic to less-busy workers by causing a busy worker to delay
1228
+ # listening on the socket, allowing workers which are not processing as many
1184
1229
  # requests to pick up new requests first.
1185
1230
  #
1186
1231
  # The default is 0.005 seconds.
1187
1232
  #
1188
- # Only works on MRI. For all other interpreters, this setting does nothing.
1233
+ # To turn off this feature, set the value to 0.
1234
+ #
1235
+ # @note Cluster mode with >= 2 workers only.
1236
+ #
1237
+ # @note Interpreters with forking support only.
1189
1238
  #
1190
1239
  # @see Puma::Server#handle_servers
1191
1240
  # @see Puma::ThreadPool#wait_for_less_busy_worker
@@ -1270,16 +1319,24 @@ module Puma
1270
1319
  @options[:fork_worker] = Integer(after_requests)
1271
1320
  end
1272
1321
 
1273
- # The number of requests to attempt inline before sending a client back to
1274
- # the reactor to be subject to normal ordering.
1322
+ # @deprecated Use {#max_keep_alive} instead.
1275
1323
  #
1276
- # The default is 10.
1324
+ def max_fast_inline(num_of_requests)
1325
+ Puma.deprecate_method_change :max_fast_inline, __method__, :max_keep_alive
1326
+ @options[:max_keep_alive] ||= Float(num_of_requests) unless num_of_requests.nil?
1327
+ end
1328
+
1329
+ # The number of requests a keep-alive client can submit before being closed.
1330
+ # Note that some applications (server to server) may benefit from a very high
1331
+ # number or Float::INFINITY.
1332
+ #
1333
+ # The default is 999.
1277
1334
  #
1278
1335
  # @example
1279
- # max_fast_inline 20
1336
+ # max_keep_alive 20
1280
1337
  #
1281
- def max_fast_inline(num_of_requests)
1282
- @options[:max_fast_inline] = Float(num_of_requests)
1338
+ def max_keep_alive(num_of_requests)
1339
+ @options[:max_keep_alive] = Float(num_of_requests) unless num_of_requests.nil?
1283
1340
  end
1284
1341
 
1285
1342
  # When `true`, keep-alive connections are maintained on inbound requests.
@@ -1409,30 +1466,21 @@ module Puma
1409
1466
  end
1410
1467
  end
1411
1468
 
1412
- def process_hook(options_key, key, block, meth)
1469
+ def process_hook(options_key, key, block, cluster_only: false)
1470
+ raise ArgumentError, "expected #{options_key} to be given a block" unless block
1471
+
1472
+ @config.hooks[options_key] = true
1473
+
1413
1474
  @options[options_key] ||= []
1414
- if ON_WORKER_KEY.include? key.class
1415
- @options[options_key] << [block, key.to_sym]
1475
+ hook_options = { block: block, cluster_only: cluster_only }
1476
+ hook_options[:id] = if ON_WORKER_KEY.include?(key.class)
1477
+ key.to_sym
1416
1478
  elsif key.nil?
1417
- @options[options_key] << block
1479
+ nil
1418
1480
  else
1419
- raise "'#{meth}' key must be String or Symbol"
1420
- end
1421
- end
1422
-
1423
- def warn_if_in_single_mode(hook_name)
1424
- return if @options[:silence_fork_callback_warning]
1425
- # user_options (CLI) have precedence over config file
1426
- workers_val = @config.options.user_options[:workers] || @options[:workers] ||
1427
- @config.puma_default_options[:workers] || 0
1428
- if workers_val == 0
1429
- log_string =
1430
- "Warning: You specified code to run in a `#{hook_name}` block, " \
1431
- "but Puma is not configured to run in cluster mode (worker count > 0), " \
1432
- "so your `#{hook_name}` block will not run."
1433
-
1434
- LogWriter.stdio.log(log_string)
1481
+ raise "'#{options_key}' key must be String or Symbol"
1435
1482
  end
1483
+ @options[options_key] << hook_options
1436
1484
  end
1437
1485
  end
1438
1486
  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
data/lib/puma/events.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Puma
4
4
 
5
5
  # This is an event sink used by `Puma::Server` to handle
6
- # lifecycle events such as :on_booted, :on_restart, and :on_stopped.
6
+ # lifecycle events such as :after_booted, :before_restart, and :after_stopped.
7
7
  # Using `Puma::DSL` it is possible to register callback hooks
8
8
  # for each event type.
9
9
  class Events
@@ -30,28 +30,43 @@ module Puma
30
30
  h
31
31
  end
32
32
 
33
+ def after_booted(&block)
34
+ register(:after_booted, &block)
35
+ end
36
+
37
+ def before_restart(&block)
38
+ register(:before_restart, &block)
39
+ end
40
+
41
+ def after_stopped(&block)
42
+ register(:after_stopped, &block)
43
+ end
44
+
33
45
  def on_booted(&block)
34
- register(:on_booted, &block)
46
+ Puma.deprecate_method_change :on_booted, __callee__, :after_booted
47
+ after_booted(&block)
35
48
  end
36
49
 
37
50
  def on_restart(&block)
38
- register(:on_restart, &block)
51
+ Puma.deprecate_method_change :on_restart, __callee__, :before_restart
52
+ before_restart(&block)
39
53
  end
40
54
 
41
55
  def on_stopped(&block)
42
- register(:on_stopped, &block)
56
+ Puma.deprecate_method_change :on_stopped, __callee__, :after_stopped
57
+ after_stopped(&block)
43
58
  end
44
59
 
45
- def fire_on_booted!
46
- fire(:on_booted)
60
+ def fire_after_booted!
61
+ fire(:after_booted)
47
62
  end
48
63
 
49
- def fire_on_restart!
50
- fire(:on_restart)
64
+ def fire_before_restart!
65
+ fire(:before_restart)
51
66
  end
52
67
 
53
- def fire_on_stopped!
54
- fire(:on_stopped)
68
+ def fire_after_stopped!
69
+ fire(:after_stopped)
55
70
  end
56
71
  end
57
72
  end
@@ -34,13 +34,17 @@ module Puma
34
34
 
35
35
  alias_method :clear, :reset
36
36
 
37
- # before Ruby 2.5, `write` would only take one argument
38
- if RUBY_VERSION >= '2.5' && RUBY_ENGINE != 'truffleruby'
39
- alias_method :append, :write
40
- else
37
+ # Create an `IoBuffer#append` method that accepts multiple strings and writes them
38
+ if RUBY_ENGINE == 'truffleruby'
39
+ # truffleruby (24.2.1, like ruby 3.3.7)
40
+ # StringIO.new.write("a", "b") # => `write': wrong number of arguments (given 2, expected 1) (ArgumentError)
41
41
  def append(*strs)
42
42
  strs.each { |str| write str }
43
43
  end
44
+ else
45
+ # Ruby 3+
46
+ # StringIO.new.write("a", "b") # => 2
47
+ alias_method :append, :write
44
48
  end
45
49
  end
46
50
  end
@@ -37,7 +37,7 @@ module Puma
37
37
  ENV['PUMA_BUNDLER_PRUNED'] = '1'
38
38
  ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
39
39
  args = [Gem.ruby, puma_wild_path, '-I', dirs.join(':')] + @original_argv
40
- # Ruby 2.0+ defaults to true which breaks socket activation
40
+ # Defaults to true which breaks socket activation
41
41
  args += [{:close_others => false}]
42
42
  Kernel.exec(*args)
43
43
  end