puma 7.2.2-java → 8.0.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.
- checksums.yaml +4 -4
- data/History.md +39 -22
- data/README.md +1 -2
- data/docs/5.0-Upgrade.md +98 -0
- data/docs/6.0-Upgrade.md +56 -0
- data/docs/7.0-Upgrade.md +52 -0
- data/docs/8.0-Upgrade.md +100 -0
- data/docs/grpc.md +62 -0
- data/docs/images/favicon.svg +1 -0
- data/docs/images/running-puma.svg +1 -0
- data/docs/images/standard-logo.svg +1 -0
- data/docs/signals.md +1 -1
- data/ext/puma_http11/http11_parser.java.rl +51 -65
- data/ext/puma_http11/mini_ssl.c +1 -8
- data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +168 -104
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +71 -85
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +34 -44
- data/ext/puma_http11/puma_http11.c +3 -4
- data/lib/puma/cli.rb +1 -1
- data/lib/puma/client.rb +114 -196
- data/lib/puma/client_env.rb +171 -0
- data/lib/puma/cluster.rb +1 -1
- data/lib/puma/configuration.rb +69 -8
- data/lib/puma/const.rb +3 -7
- data/lib/puma/control_cli.rb +4 -15
- data/lib/puma/detect.rb +11 -0
- data/lib/puma/dsl.rb +75 -22
- data/lib/puma/launcher.rb +3 -4
- data/lib/puma/minissl.rb +56 -101
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/reactor.rb +3 -35
- data/lib/puma/{request.rb → response.rb} +16 -201
- data/lib/puma/server.rb +84 -120
- data/lib/puma/server_plugin_control.rb +32 -0
- data/lib/puma/thread_pool.rb +129 -23
- data/lib/puma/util.rb +4 -8
- data/lib/rack/handler/puma.rb +1 -1
- metadata +14 -3
data/lib/puma/server.rb
CHANGED
|
@@ -11,7 +11,7 @@ require_relative 'reactor'
|
|
|
11
11
|
require_relative 'client'
|
|
12
12
|
require_relative 'binder'
|
|
13
13
|
require_relative 'util'
|
|
14
|
-
require_relative '
|
|
14
|
+
require_relative 'response'
|
|
15
15
|
require_relative 'configuration'
|
|
16
16
|
require_relative 'cluster_accept_loop_delay'
|
|
17
17
|
|
|
@@ -31,15 +31,15 @@ module Puma
|
|
|
31
31
|
# Each `Puma::Server` will have one reactor and one thread pool.
|
|
32
32
|
class Server
|
|
33
33
|
module FiberPerRequest
|
|
34
|
-
def handle_request(client, requests)
|
|
34
|
+
def handle_request(processor, client, requests)
|
|
35
35
|
Fiber.new do
|
|
36
36
|
super
|
|
37
37
|
end.resume
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
include
|
|
42
|
-
include
|
|
41
|
+
include Const
|
|
42
|
+
include Response
|
|
43
43
|
|
|
44
44
|
attr_reader :options
|
|
45
45
|
attr_reader :thread
|
|
@@ -51,7 +51,7 @@ module Puma
|
|
|
51
51
|
# @todo the following may be deprecated in the future
|
|
52
52
|
attr_reader :auto_trim_time, :early_hints, :first_data_timeout,
|
|
53
53
|
:leak_stack_on_error,
|
|
54
|
-
:persistent_timeout, :reaping_time
|
|
54
|
+
:persistent_timeout, :reaping_time
|
|
55
55
|
|
|
56
56
|
attr_accessor :app
|
|
57
57
|
attr_accessor :binder
|
|
@@ -98,8 +98,6 @@ module Puma
|
|
|
98
98
|
@early_hints = @options[:early_hints]
|
|
99
99
|
@first_data_timeout = @options[:first_data_timeout]
|
|
100
100
|
@persistent_timeout = @options[:persistent_timeout]
|
|
101
|
-
@shutdown_body_timeout = @options[:shutdown_body_timeout]
|
|
102
|
-
@shutdown_body_deadline = nil
|
|
103
101
|
@idle_timeout = @options[:idle_timeout]
|
|
104
102
|
@min_threads = @options[:min_threads]
|
|
105
103
|
@max_threads = @options[:max_threads]
|
|
@@ -260,9 +258,10 @@ module Puma
|
|
|
260
258
|
@events.fire :state, :booting
|
|
261
259
|
|
|
262
260
|
@status = :run
|
|
263
|
-
@shutdown_body_deadline = nil
|
|
264
261
|
|
|
265
|
-
@thread_pool = ThreadPool.new(thread_name, options, server: self)
|
|
262
|
+
@thread_pool = ThreadPool.new(thread_name, options, server: self) do |processor, client|
|
|
263
|
+
process_client(processor, client)
|
|
264
|
+
end
|
|
266
265
|
|
|
267
266
|
if @queue_requests
|
|
268
267
|
@reactor = Reactor.new(@io_selector_backend) { |c|
|
|
@@ -307,15 +306,12 @@ module Puma
|
|
|
307
306
|
# The method checks to see if it has the full header and body with
|
|
308
307
|
# the `Puma::Client#try_to_finish` method. If the full request has been sent,
|
|
309
308
|
# then the request is passed to the ThreadPool (`@thread_pool << client`)
|
|
310
|
-
# so that a "
|
|
309
|
+
# so that a "processor thread" can pick up the request and begin to execute application logic.
|
|
311
310
|
# The Client is then removed from the reactor (return `true`).
|
|
312
311
|
#
|
|
313
312
|
# If a client object times out, a 408 response is written, its connection is closed,
|
|
314
313
|
# and the object is removed from the reactor (return `true`).
|
|
315
314
|
#
|
|
316
|
-
# If the request cannot be read, the Client is passed to the ThreadPool with its
|
|
317
|
-
# `reactor_error` set, so that a processor thread writes the error response.
|
|
318
|
-
#
|
|
319
315
|
# If the Reactor is shutting down, all Clients are either timed out or passed to the
|
|
320
316
|
# ThreadPool, depending on their current state (#can_close?).
|
|
321
317
|
#
|
|
@@ -324,32 +320,17 @@ module Puma
|
|
|
324
320
|
# will wake up and again be checked to see if it's ready to be passed to the thread pool.
|
|
325
321
|
def reactor_wakeup(client)
|
|
326
322
|
shutdown = !@queue_requests
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
hand_to_thread_pool client
|
|
323
|
+
if client.try_to_finish || (shutdown && !client.can_close?)
|
|
324
|
+
@thread_pool << client
|
|
330
325
|
elsif shutdown || client.timeout == 0
|
|
331
326
|
client.timeout!
|
|
332
327
|
else
|
|
333
|
-
client.set_timeout(@first_data_timeout)
|
|
328
|
+
client.set_timeout(@first_data_timeout)
|
|
334
329
|
false
|
|
335
330
|
end
|
|
336
|
-
rescue ConnectionError, EOFError
|
|
337
|
-
close_client_safely(client)
|
|
338
|
-
true
|
|
339
331
|
rescue StandardError => e
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
client.reactor_error = e
|
|
343
|
-
hand_to_thread_pool client
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
def hand_to_thread_pool(client)
|
|
347
|
-
@thread_pool << client
|
|
348
|
-
true
|
|
349
|
-
rescue ThreadError
|
|
350
|
-
true
|
|
351
|
-
rescue StandardError
|
|
352
|
-
close_client_safely client
|
|
332
|
+
client_error(e, client)
|
|
333
|
+
close_client_safely(client)
|
|
353
334
|
true
|
|
354
335
|
end
|
|
355
336
|
|
|
@@ -380,16 +361,13 @@ module Puma
|
|
|
380
361
|
ios = IO.select sockets, nil, nil, (shutting_down? ? 0 : @idle_timeout)
|
|
381
362
|
unless ios
|
|
382
363
|
unless shutting_down?
|
|
364
|
+
@idle_timeout_reached = true
|
|
365
|
+
|
|
383
366
|
if @clustered
|
|
384
|
-
|
|
385
|
-
@idle_timeout_reached = true
|
|
386
|
-
@worker_write << "#{PipeRequest::PIPE_IDLE}#{Process.pid}\n" rescue nil
|
|
387
|
-
end
|
|
367
|
+
@worker_write << "#{PipeRequest::PIPE_IDLE}#{Process.pid}\n" rescue nil
|
|
388
368
|
next
|
|
389
369
|
else
|
|
390
|
-
@idle_timeout_reached = true
|
|
391
370
|
@log_writer.log "- Idle timeout reached"
|
|
392
|
-
shutdown_body_deadline
|
|
393
371
|
@status = :stop
|
|
394
372
|
end
|
|
395
373
|
end
|
|
@@ -423,11 +401,9 @@ module Puma
|
|
|
423
401
|
sock.accept_nonblock
|
|
424
402
|
rescue IO::WaitReadable
|
|
425
403
|
next
|
|
426
|
-
rescue Errno::EMFILE, Errno::ENFILE, Errno::ENOBUFS, Errno::ENOMEM => e
|
|
427
|
-
accept_resource_error e
|
|
428
|
-
next
|
|
429
404
|
end
|
|
430
405
|
drain += 1 if shutting_down?
|
|
406
|
+
|
|
431
407
|
client = new_client(io, sock)
|
|
432
408
|
client.send(addr_send_name, addr_value) if addr_value
|
|
433
409
|
pool << client
|
|
@@ -437,17 +413,11 @@ module Puma
|
|
|
437
413
|
# In the case that any of the sockets are unexpectedly close.
|
|
438
414
|
raise
|
|
439
415
|
rescue StandardError => e
|
|
440
|
-
|
|
441
|
-
@log_writer.unknown_error e, nil, "Listen loop"
|
|
442
|
-
rescue StandardError
|
|
443
|
-
end
|
|
416
|
+
@log_writer.unknown_error e, nil, "Listen loop"
|
|
444
417
|
end
|
|
445
418
|
end
|
|
446
419
|
|
|
447
|
-
|
|
448
|
-
@log_writer.debug "Drained #{drain} additional connections." if drain
|
|
449
|
-
rescue StandardError
|
|
450
|
-
end
|
|
420
|
+
@log_writer.debug "Drained #{drain} additional connections." if drain
|
|
451
421
|
@events.fire :state, @status
|
|
452
422
|
|
|
453
423
|
if queue_requests
|
|
@@ -457,10 +427,7 @@ module Puma
|
|
|
457
427
|
|
|
458
428
|
graceful_shutdown if @status == :stop || @status == :restart
|
|
459
429
|
rescue Exception => e
|
|
460
|
-
|
|
461
|
-
@log_writer.unknown_error e, nil, "Exception handling servers"
|
|
462
|
-
rescue StandardError
|
|
463
|
-
end
|
|
430
|
+
@log_writer.unknown_error e, nil, "Exception handling servers"
|
|
464
431
|
ensure
|
|
465
432
|
# Errno::EBADF is infrequently raised
|
|
466
433
|
[@check, @notify].each do |io|
|
|
@@ -480,7 +447,9 @@ module Puma
|
|
|
480
447
|
def new_client(io, sock)
|
|
481
448
|
client = Client.new(io, @binder.env(sock))
|
|
482
449
|
client.listener = sock
|
|
450
|
+
client.env_set_http_version = @env_set_http_version
|
|
483
451
|
client.http_content_length_limit = @http_content_length_limit
|
|
452
|
+
client.supported_http_methods = @supported_http_methods
|
|
484
453
|
client
|
|
485
454
|
end
|
|
486
455
|
|
|
@@ -490,14 +459,12 @@ module Puma
|
|
|
490
459
|
|
|
491
460
|
case cmd
|
|
492
461
|
when STOP_COMMAND
|
|
493
|
-
shutdown_body_deadline
|
|
494
462
|
@status = :stop
|
|
495
463
|
return true
|
|
496
464
|
when HALT_COMMAND
|
|
497
465
|
@status = :halt
|
|
498
466
|
return true
|
|
499
467
|
when RESTART_COMMAND
|
|
500
|
-
shutdown_body_deadline
|
|
501
468
|
@status = :restart
|
|
502
469
|
return true
|
|
503
470
|
end
|
|
@@ -508,22 +475,20 @@ module Puma
|
|
|
508
475
|
# Given a connection on +client+, handle the incoming requests,
|
|
509
476
|
# or queue the connection in the Reactor if no request is available.
|
|
510
477
|
#
|
|
511
|
-
# This method is called from a ThreadPool
|
|
478
|
+
# This method is called from a ThreadPool processor thread.
|
|
512
479
|
#
|
|
513
480
|
# This method supports HTTP Keep-Alive so it may, depending on if the client
|
|
514
481
|
# indicates that it supports keep alive, wait for another request before
|
|
515
482
|
# returning.
|
|
516
483
|
#
|
|
517
484
|
# Return true if one or more requests were processed.
|
|
518
|
-
def process_client(client)
|
|
485
|
+
def process_client(processor, client)
|
|
519
486
|
close_socket = true
|
|
520
487
|
|
|
521
488
|
requests = 0
|
|
522
489
|
|
|
523
490
|
begin
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
if @queue_requests && !client.eagerly_finish { shutdown_body_limit }
|
|
491
|
+
if @queue_requests && !client.eagerly_finish
|
|
527
492
|
|
|
528
493
|
client.set_timeout(@first_data_timeout)
|
|
529
494
|
if @reactor.add client
|
|
@@ -533,14 +498,14 @@ module Puma
|
|
|
533
498
|
end
|
|
534
499
|
|
|
535
500
|
with_force_shutdown(client) do
|
|
536
|
-
client.finish(@first_data_timeout)
|
|
501
|
+
client.finish(@first_data_timeout)
|
|
537
502
|
end
|
|
538
503
|
|
|
539
504
|
can_loop = true
|
|
540
505
|
while can_loop
|
|
541
506
|
can_loop = false
|
|
542
507
|
@requests_count += 1
|
|
543
|
-
case handle_request(client, requests + 1)
|
|
508
|
+
case handle_request(processor, client, requests + 1)
|
|
544
509
|
when :close
|
|
545
510
|
when :async
|
|
546
511
|
close_socket = false
|
|
@@ -554,7 +519,7 @@ module Puma
|
|
|
554
519
|
next_request_ready = if client.has_back_to_back_requests?
|
|
555
520
|
with_force_shutdown(client) { client.process_back_to_back_requests }
|
|
556
521
|
else
|
|
557
|
-
with_force_shutdown(client) { client.eagerly_finish
|
|
522
|
+
with_force_shutdown(client) { client.eagerly_finish }
|
|
558
523
|
end
|
|
559
524
|
|
|
560
525
|
if next_request_ready
|
|
@@ -586,25 +551,6 @@ module Puma
|
|
|
586
551
|
end
|
|
587
552
|
end
|
|
588
553
|
|
|
589
|
-
# Accepting fails while the process is out of file descriptors or memory.
|
|
590
|
-
# The connection stays in the backlog, so retrying at once would spin and
|
|
591
|
-
# log at full speed. Wait briefly and log at most once per second.
|
|
592
|
-
def accept_resource_error(error)
|
|
593
|
-
now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
594
|
-
if @accept_error_logged_at.nil? || now - @accept_error_logged_at >= 1
|
|
595
|
-
suffix = @accept_errors_suppressed.to_i > 0 ? " (#{@accept_errors_suppressed} more suppressed)" : ""
|
|
596
|
-
@accept_error_logged_at = now
|
|
597
|
-
@accept_errors_suppressed = 0
|
|
598
|
-
begin
|
|
599
|
-
@log_writer.unknown_error error, nil, "Listen loop#{suffix}"
|
|
600
|
-
rescue StandardError
|
|
601
|
-
end
|
|
602
|
-
else
|
|
603
|
-
@accept_errors_suppressed += 1
|
|
604
|
-
end
|
|
605
|
-
sleep ACCEPT_ERROR_DELAY
|
|
606
|
-
end
|
|
607
|
-
|
|
608
554
|
# :nodoc:
|
|
609
555
|
def close_client_safely(client)
|
|
610
556
|
client.close
|
|
@@ -636,7 +582,7 @@ module Puma
|
|
|
636
582
|
lowlevel_error(e, client.env)
|
|
637
583
|
@log_writer.ssl_error e, client.io
|
|
638
584
|
when HttpParserError
|
|
639
|
-
response_to_error(client, requests, e, 400)
|
|
585
|
+
response_to_error(client, requests, e, client.error_status_code || 400)
|
|
640
586
|
@log_writer.parse_error e, client
|
|
641
587
|
when HttpParserError501
|
|
642
588
|
response_to_error(client, requests, e, 501)
|
|
@@ -669,50 +615,27 @@ module Puma
|
|
|
669
615
|
end
|
|
670
616
|
|
|
671
617
|
def response_to_error(client, requests, err, status_code)
|
|
672
|
-
|
|
618
|
+
# @todo remove sometime later
|
|
619
|
+
if status_code == 413
|
|
620
|
+
status = 413
|
|
621
|
+
res_body = ["Payload Too Large"]
|
|
622
|
+
headers = {}
|
|
623
|
+
headers[CONTENT_LENGTH2] = 17
|
|
624
|
+
else
|
|
625
|
+
status, headers, res_body = lowlevel_error(err, client.env, status_code)
|
|
626
|
+
end
|
|
673
627
|
prepare_response(status, headers, res_body, requests, client)
|
|
674
628
|
end
|
|
675
629
|
private :response_to_error
|
|
676
630
|
|
|
677
|
-
def shutdown_body_deadline
|
|
678
|
-
@shutdown_body_deadline ||= Process.clock_gettime(Process::CLOCK_MONOTONIC) + @shutdown_body_timeout
|
|
679
|
-
end
|
|
680
|
-
|
|
681
|
-
def shutdown_body_limit
|
|
682
|
-
@shutdown_body_deadline
|
|
683
|
-
end
|
|
684
|
-
|
|
685
631
|
# Wait for all outstanding requests to finish.
|
|
686
632
|
#
|
|
687
633
|
def graceful_shutdown
|
|
688
|
-
shutdown_body_deadline
|
|
689
|
-
|
|
690
|
-
if options[:shutdown_debug]
|
|
691
|
-
threads = Thread.list
|
|
692
|
-
total = threads.size
|
|
693
|
-
|
|
694
|
-
pid = Process.pid
|
|
695
|
-
|
|
696
|
-
$stdout.syswrite "#{pid}: === Begin thread backtrace dump ===\n"
|
|
697
|
-
|
|
698
|
-
threads.each_with_index do |t,i|
|
|
699
|
-
$stdout.syswrite "#{pid}: Thread #{i+1}/#{total}: #{t.inspect}\n"
|
|
700
|
-
$stdout.syswrite "#{pid}: #{t.backtrace.join("\n#{pid}: ")}\n\n"
|
|
701
|
-
end
|
|
702
|
-
$stdout.syswrite "#{pid}: === End thread backtrace dump ===\n"
|
|
703
|
-
end
|
|
704
|
-
|
|
705
634
|
if @status != :restart
|
|
706
635
|
@binder.close
|
|
707
636
|
end
|
|
708
637
|
|
|
709
|
-
|
|
710
|
-
if timeout = options[:force_shutdown_after]
|
|
711
|
-
@thread_pool.shutdown timeout.to_f
|
|
712
|
-
else
|
|
713
|
-
@thread_pool.shutdown
|
|
714
|
-
end
|
|
715
|
-
end
|
|
638
|
+
@thread_pool.shutdown(options[:force_shutdown_after])
|
|
716
639
|
end
|
|
717
640
|
|
|
718
641
|
def notify_safely(message)
|
|
@@ -729,11 +652,10 @@ module Puma
|
|
|
729
652
|
end
|
|
730
653
|
private :notify_safely
|
|
731
654
|
|
|
732
|
-
# Stops the acceptor thread and then causes the
|
|
655
|
+
# Stops the acceptor thread and then causes the processor threads to finish
|
|
733
656
|
# off the request queue before finally exiting.
|
|
734
657
|
|
|
735
658
|
def stop(sync=false)
|
|
736
|
-
shutdown_body_deadline
|
|
737
659
|
notify_safely(STOP_COMMAND)
|
|
738
660
|
@thread.join if @thread && sync
|
|
739
661
|
end
|
|
@@ -744,7 +666,6 @@ module Puma
|
|
|
744
666
|
end
|
|
745
667
|
|
|
746
668
|
def begin_restart(sync=false)
|
|
747
|
-
shutdown_body_deadline
|
|
748
669
|
notify_safely(RESTART_COMMAND)
|
|
749
670
|
@thread.join if @thread && sync
|
|
750
671
|
end
|
|
@@ -801,6 +722,49 @@ module Puma
|
|
|
801
722
|
@binder.add_unix_listener path, umask, mode, backlog
|
|
802
723
|
end
|
|
803
724
|
|
|
725
|
+
# Updates the minimum and maximum number of threads in the thread pool.
|
|
726
|
+
#
|
|
727
|
+
# This method allows dynamic adjustment of the thread pool size while the server
|
|
728
|
+
# is running. It validates the provided values and updates both the thread pool
|
|
729
|
+
# and the server's thread configuration.
|
|
730
|
+
#
|
|
731
|
+
# @param min [Integer] The minimum number of threads to maintain in the pool.
|
|
732
|
+
# Defaults to the current minimum if not specified. Must be greater than 0
|
|
733
|
+
# and less than or equal to max.
|
|
734
|
+
# @param max [Integer] The maximum number of threads allowed in the pool.
|
|
735
|
+
# Defaults to the current maximum if not specified. Must be greater than or
|
|
736
|
+
# equal to min.
|
|
737
|
+
#
|
|
738
|
+
# @return [void]
|
|
739
|
+
#
|
|
740
|
+
# @note If validation fails, a warning message is logged and no changes are made.
|
|
741
|
+
#
|
|
742
|
+
# @example Update both min and max threads
|
|
743
|
+
# server.update_thread_pool_min_max(min: 2, max: 8)
|
|
744
|
+
#
|
|
745
|
+
# @example Update only the minimum threads
|
|
746
|
+
# server.update_thread_pool_min_max(min: 4)
|
|
747
|
+
#
|
|
748
|
+
# @example Update only the maximum threads
|
|
749
|
+
# server.update_thread_pool_min_max(max: 16)
|
|
750
|
+
#
|
|
751
|
+
def update_thread_pool_min_max(min: @min_threads, max: @max_threads)
|
|
752
|
+
if min > max
|
|
753
|
+
@log_writer.log "`min' value cannot be greater than `max' value."
|
|
754
|
+
return
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
if min < 0
|
|
758
|
+
@log_writer.log "`min' value cannot be less than 0"
|
|
759
|
+
return
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
@thread_pool&.with_mutex do
|
|
763
|
+
@thread_pool.min, @thread_pool.max = min, max
|
|
764
|
+
@min_threads, @max_threads = min, max
|
|
765
|
+
end
|
|
766
|
+
end
|
|
767
|
+
|
|
804
768
|
# @!attribute [r] connected_ports
|
|
805
769
|
def connected_ports
|
|
806
770
|
@binder.connected_ports
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Puma
|
|
2
|
+
# ServerPluginControl provides a control interface for server plugins to
|
|
3
|
+
# interact with and manage server settings dynamically.
|
|
4
|
+
#
|
|
5
|
+
# This class acts as a facade between plugins and the Puma server,
|
|
6
|
+
# allowing plugins to safely modify server configuration and thread pool
|
|
7
|
+
# settings without direct access to the server's internal state.
|
|
8
|
+
#
|
|
9
|
+
class ServerPluginControl
|
|
10
|
+
def initialize(server)
|
|
11
|
+
@server = server
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Returns the maximum number of threads in the thread pool.
|
|
15
|
+
def max_threads
|
|
16
|
+
@server.max_threads
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns the minimum number of threads in the thread pool.
|
|
20
|
+
def min_threads
|
|
21
|
+
@server.min_threads
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Updates the minimum and maximum number of threads in the thread pool.
|
|
25
|
+
#
|
|
26
|
+
# @see Puma::Server#update_thread_pool_min_max
|
|
27
|
+
#
|
|
28
|
+
def update_thread_pool_min_max(min: max_threads, max: min_threads)
|
|
29
|
+
@server.update_thread_pool_min_max(min: min, max: max)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|