puma 3.9.1-java → 3.10.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.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +29 -0
- data/README.md +124 -229
- data/docs/plugins.md +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +102 -37
- data/ext/puma_http11/http11_parser.c +130 -146
- data/ext/puma_http11/http11_parser.rl +9 -9
- data/ext/puma_http11/mini_ssl.c +2 -2
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +13 -16
- data/lib/puma/app/status.rb +8 -0
- data/lib/puma/binder.rb +6 -5
- data/lib/puma/client.rb +1 -0
- data/lib/puma/cluster.rb +8 -2
- data/lib/puma/configuration.rb +3 -2
- data/lib/puma/const.rb +3 -2
- data/lib/puma/control_cli.rb +2 -2
- data/lib/puma/dsl.rb +10 -0
- data/lib/puma/jruby_restart.rb +0 -1
- data/lib/puma/launcher.rb +31 -14
- data/lib/puma/minissl.rb +19 -25
- data/lib/puma/plugin/tmp_restart.rb +0 -1
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/reactor.rb +3 -0
- data/lib/puma/server.rb +25 -19
- data/lib/puma/thread_pool.rb +2 -2
- data/lib/rack/handler/puma.rb +2 -0
- data/tools/jungle/README.md +4 -0
- data/tools/trickletest.rb +1 -1
- metadata +9 -57
- data/.github/issue_template.md +0 -20
- data/DEPLOYMENT.md +0 -91
- data/Gemfile +0 -14
- data/Manifest.txt +0 -78
- data/Rakefile +0 -165
- data/Release.md +0 -9
- data/gemfiles/2.1-Gemfile +0 -12
- data/puma.gemspec +0 -20
    
        data/lib/puma/minissl.rb
    CHANGED
    
    | @@ -96,35 +96,29 @@ module Puma | |
| 96 96 | 
             
                    @socket.flush
         | 
| 97 97 | 
             
                  end
         | 
| 98 98 |  | 
| 99 | 
            -
                  def  | 
| 100 | 
            -
                     | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
                        return unless IO.select([@socket], nil, nil, 1)
         | 
| 108 | 
            -
                        begin
         | 
| 109 | 
            -
                          read_nonblock(1024)
         | 
| 110 | 
            -
                        rescue Errno::EAGAIN
         | 
| 111 | 
            -
                        end
         | 
| 112 | 
            -
                      end
         | 
| 113 | 
            -
             | 
| 114 | 
            -
                      done = @engine.shutdown
         | 
| 115 | 
            -
             | 
| 116 | 
            -
                      while true
         | 
| 117 | 
            -
                        enc = @engine.extract
         | 
| 118 | 
            -
                        @socket.write enc
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                        notify = @socket.sysread(1024)
         | 
| 99 | 
            +
                  def read_and_drop(timeout = 1)
         | 
| 100 | 
            +
                    return :timeout unless IO.select([@socket], nil, nil, timeout)
         | 
| 101 | 
            +
                    read_nonblock(1024)
         | 
| 102 | 
            +
                    :drop
         | 
| 103 | 
            +
                  rescue Errno::EAGAIN
         | 
| 104 | 
            +
                    # do nothing
         | 
| 105 | 
            +
                    :eagain
         | 
| 106 | 
            +
                  end
         | 
| 121 107 |  | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 108 | 
            +
                  def should_drop_bytes?
         | 
| 109 | 
            +
                    @engine.init? || !@engine.shutdown
         | 
| 110 | 
            +
                  end
         | 
| 124 111 |  | 
| 125 | 
            -
             | 
| 112 | 
            +
                  def close
         | 
| 113 | 
            +
                    begin
         | 
| 114 | 
            +
                      # Read any drop any partially initialized sockets and any received bytes during shutdown.
         | 
| 115 | 
            +
                      # Don't let this socket hold this loop forever.
         | 
| 116 | 
            +
                      # If it can't send more packets within 1s, then give up.
         | 
| 117 | 
            +
                      while should_drop_bytes?
         | 
| 118 | 
            +
                        return if read_and_drop(1) == :timeout
         | 
| 126 119 | 
             
                      end
         | 
| 127 120 | 
             
                    rescue IOError, SystemCallError
         | 
| 121 | 
            +
                      Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 128 122 | 
             
                      # nothing
         | 
| 129 123 | 
             
                    ensure
         | 
| 130 124 | 
             
                      @socket.close
         | 
    
        data/lib/puma/puma_http11.jar
    CHANGED
    
    | Binary file | 
    
        data/lib/puma/reactor.rb
    CHANGED
    
    | @@ -28,6 +28,7 @@ module Puma | |
| 28 28 | 
             
                    begin
         | 
| 29 29 | 
             
                      ready = IO.select sockets, nil, nil, @sleep_for
         | 
| 30 30 | 
             
                    rescue IOError => e
         | 
| 31 | 
            +
                      Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 31 32 | 
             
                      if sockets.any? { |socket| socket.closed? }
         | 
| 32 33 | 
             
                        STDERR.puts "Error in select: #{e.message} (#{e.class})"
         | 
| 33 34 | 
             
                        STDERR.puts e.backtrace
         | 
| @@ -195,6 +196,7 @@ module Puma | |
| 195 196 | 
             
                  begin
         | 
| 196 197 | 
             
                    @trigger << "c"
         | 
| 197 198 | 
             
                  rescue IOError
         | 
| 199 | 
            +
                    Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 198 200 | 
             
                  end
         | 
| 199 201 | 
             
                end
         | 
| 200 202 |  | 
| @@ -202,6 +204,7 @@ module Puma | |
| 202 204 | 
             
                  begin
         | 
| 203 205 | 
             
                    @trigger << "!"
         | 
| 204 206 | 
             
                  rescue IOError
         | 
| 207 | 
            +
                    Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 205 208 | 
             
                  end
         | 
| 206 209 |  | 
| 207 210 | 
             
                  @thread.join
         | 
    
        data/lib/puma/server.rb
    CHANGED
    
    | @@ -64,12 +64,11 @@ module Puma | |
| 64 64 | 
             
                  @thread_pool = nil
         | 
| 65 65 |  | 
| 66 66 | 
             
                  @persistent_timeout = options.fetch(:persistent_timeout, PERSISTENT_TIMEOUT)
         | 
| 67 | 
            +
                  @first_data_timeout = options.fetch(:first_data_timeout, FIRST_DATA_TIMEOUT)
         | 
| 67 68 |  | 
| 68 69 | 
             
                  @binder = Binder.new(events)
         | 
| 69 70 | 
             
                  @own_binder = true
         | 
| 70 71 |  | 
| 71 | 
            -
                  @first_data_timeout = FIRST_DATA_TIMEOUT
         | 
| 72 | 
            -
             | 
| 73 72 | 
             
                  @leak_stack_on_error = true
         | 
| 74 73 |  | 
| 75 74 | 
             
                  @options = options
         | 
| @@ -111,6 +110,7 @@ module Puma | |
| 111 110 | 
             
                    begin
         | 
| 112 111 | 
             
                      socket.setsockopt(6, 3, 1) if socket.kind_of? TCPSocket
         | 
| 113 112 | 
             
                    rescue IOError, SystemCallError
         | 
| 113 | 
            +
                      Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 114 114 | 
             
                    end
         | 
| 115 115 | 
             
                  end
         | 
| 116 116 |  | 
| @@ -118,6 +118,7 @@ module Puma | |
| 118 118 | 
             
                    begin
         | 
| 119 119 | 
             
                      socket.setsockopt(6, 3, 0) if socket.kind_of? TCPSocket
         | 
| 120 120 | 
             
                    rescue IOError, SystemCallError
         | 
| 121 | 
            +
                      Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 121 122 | 
             
                    end
         | 
| 122 123 | 
             
                  end
         | 
| 123 124 |  | 
| @@ -128,6 +129,7 @@ module Puma | |
| 128 129 | 
             
                    begin
         | 
| 129 130 | 
             
                      tcp_info = socket.getsockopt(Socket::SOL_TCP, Socket::TCP_INFO)
         | 
| 130 131 | 
             
                    rescue IOError, SystemCallError
         | 
| 132 | 
            +
                      Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 131 133 | 
             
                      @precheck_closing = false
         | 
| 132 134 | 
             
                      false
         | 
| 133 135 | 
             
                    else
         | 
| @@ -491,6 +493,7 @@ module Puma | |
| 491 493 | 
             
                    begin
         | 
| 492 494 | 
             
                      client.close if close_socket
         | 
| 493 495 | 
             
                    rescue IOError, SystemCallError
         | 
| 496 | 
            +
                      Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 494 497 | 
             
                      # Already closed
         | 
| 495 498 | 
             
                    rescue StandardError => e
         | 
| 496 499 | 
             
                      @events.unknown_error self, e, "Client"
         | 
| @@ -893,35 +896,38 @@ module Puma | |
| 893 896 | 
             
                  end
         | 
| 894 897 | 
             
                end
         | 
| 895 898 |  | 
| 896 | 
            -
                 | 
| 897 | 
            -
                # off the request queue before finally exiting.
         | 
| 898 | 
            -
                #
         | 
| 899 | 
            -
                def stop(sync=false)
         | 
| 899 | 
            +
                def notify_safely(message)
         | 
| 900 900 | 
             
                  begin
         | 
| 901 | 
            -
                    @notify <<  | 
| 901 | 
            +
                    @notify << message
         | 
| 902 902 | 
             
                  rescue IOError
         | 
| 903 | 
            -
             | 
| 903 | 
            +
                     # The server, in another thread, is shutting down
         | 
| 904 | 
            +
                    Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 905 | 
            +
                  rescue RuntimeError => e
         | 
| 906 | 
            +
                    # Temporary workaround for https://bugs.ruby-lang.org/issues/13239
         | 
| 907 | 
            +
                    if e.message.include?('IOError')
         | 
| 908 | 
            +
                      Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 909 | 
            +
                    else
         | 
| 910 | 
            +
                      raise e
         | 
| 911 | 
            +
                    end
         | 
| 904 912 | 
             
                  end
         | 
| 913 | 
            +
                end
         | 
| 914 | 
            +
                private :notify_safely
         | 
| 905 915 |  | 
| 916 | 
            +
                # Stops the acceptor thread and then causes the worker threads to finish
         | 
| 917 | 
            +
                # off the request queue before finally exiting.
         | 
| 918 | 
            +
             | 
| 919 | 
            +
                def stop(sync=false)
         | 
| 920 | 
            +
                  notify_safely(STOP_COMMAND)
         | 
| 906 921 | 
             
                  @thread.join if @thread && sync
         | 
| 907 922 | 
             
                end
         | 
| 908 923 |  | 
| 909 924 | 
             
                def halt(sync=false)
         | 
| 910 | 
            -
                   | 
| 911 | 
            -
                    @notify << HALT_COMMAND
         | 
| 912 | 
            -
                  rescue IOError
         | 
| 913 | 
            -
                    # The server, in another thread, is shutting down
         | 
| 914 | 
            -
                  end
         | 
| 915 | 
            -
             | 
| 925 | 
            +
                  notify_safely(HALT_COMMAND)
         | 
| 916 926 | 
             
                  @thread.join if @thread && sync
         | 
| 917 927 | 
             
                end
         | 
| 918 928 |  | 
| 919 929 | 
             
                def begin_restart
         | 
| 920 | 
            -
                   | 
| 921 | 
            -
                    @notify << RESTART_COMMAND
         | 
| 922 | 
            -
                  rescue IOError
         | 
| 923 | 
            -
                    # The server, in another thread, is shutting down
         | 
| 924 | 
            -
                  end
         | 
| 930 | 
            +
                  notify_safely(RESTART_COMMAND)
         | 
| 925 931 | 
             
                end
         | 
| 926 932 |  | 
| 927 933 | 
             
                def fast_write(io, str)
         | 
    
        data/lib/puma/thread_pool.rb
    CHANGED
    
    | @@ -71,9 +71,9 @@ module Puma | |
| 71 71 | 
             
                def spawn_thread
         | 
| 72 72 | 
             
                  @spawned += 1
         | 
| 73 73 |  | 
| 74 | 
            -
                  th = Thread.new do
         | 
| 74 | 
            +
                  th = Thread.new(@spawned) do |spawned|
         | 
| 75 75 | 
             
                    # Thread name is new in Ruby 2.3
         | 
| 76 | 
            -
                    Thread.current.name = 'puma %03i' %  | 
| 76 | 
            +
                    Thread.current.name = 'puma %03i' % spawned if Thread.current.respond_to?(:name=)
         | 
| 77 77 | 
             
                    todo  = @todo
         | 
| 78 78 | 
             
                    block = @block
         | 
| 79 79 | 
             
                    mutex = @mutex
         | 
    
        data/lib/rack/handler/puma.rb
    CHANGED
    
    
    
        data/tools/jungle/README.md
    CHANGED
    
    
    
        data/tools/trickletest.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,80 +1,36 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: puma
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3. | 
| 4 | 
            +
              version: 3.10.0
         | 
| 5 5 | 
             
            platform: java
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Evan Phoenix
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2017- | 
| 12 | 
            -
            dependencies:
         | 
| 13 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 15 | 
            -
                requirements:
         | 
| 16 | 
            -
                - - "~>"
         | 
| 17 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 18 | 
            -
                    version: '4.0'
         | 
| 19 | 
            -
              name: rdoc
         | 
| 20 | 
            -
              prerelease: false
         | 
| 21 | 
            -
              type: :development
         | 
| 22 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            -
                requirements:
         | 
| 24 | 
            -
                - - "~>"
         | 
| 25 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            -
                    version: '4.0'
         | 
| 27 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 29 | 
            -
                requirements:
         | 
| 30 | 
            -
                - - "~>"
         | 
| 31 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 32 | 
            -
                    version: '3.15'
         | 
| 33 | 
            -
              name: hoe
         | 
| 34 | 
            -
              prerelease: false
         | 
| 35 | 
            -
              type: :development
         | 
| 36 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            -
                requirements:
         | 
| 38 | 
            -
                - - "~>"
         | 
| 39 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            -
                    version: '3.15'
         | 
| 11 | 
            +
            date: 2017-08-17 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies: []
         | 
| 41 13 | 
             
            description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server
         | 
| 42 14 | 
             
              for Ruby/Rack applications. Puma is intended for use in both development and production
         | 
| 43 | 
            -
              environments.  | 
| 44 | 
            -
               | 
| 15 | 
            +
              environments. It's great for highly concurrent Ruby implementations such as Rubinius
         | 
| 16 | 
            +
              and JRuby as well as as providing process worker support to support CRuby well.
         | 
| 45 17 | 
             
            email:
         | 
| 46 18 | 
             
            - evan@phx.io
         | 
| 47 19 | 
             
            executables:
         | 
| 48 20 | 
             
            - puma
         | 
| 49 21 | 
             
            - pumactl
         | 
| 50 22 | 
             
            extensions: []
         | 
| 51 | 
            -
            extra_rdoc_files:
         | 
| 52 | 
            -
            - ".github/issue_template.md"
         | 
| 53 | 
            -
            - DEPLOYMENT.md
         | 
| 54 | 
            -
            - History.md
         | 
| 55 | 
            -
            - Manifest.txt
         | 
| 56 | 
            -
            - README.md
         | 
| 57 | 
            -
            - Release.md
         | 
| 58 | 
            -
            - docs/nginx.md
         | 
| 59 | 
            -
            - docs/signals.md
         | 
| 60 | 
            -
            - docs/systemd.md
         | 
| 61 | 
            -
            - tools/jungle/README.md
         | 
| 62 | 
            -
            - tools/jungle/init.d/README.md
         | 
| 63 | 
            -
            - tools/jungle/upstart/README.md
         | 
| 23 | 
            +
            extra_rdoc_files: []
         | 
| 64 24 | 
             
            files:
         | 
| 65 | 
            -
            - ".github/issue_template.md"
         | 
| 66 | 
            -
            - DEPLOYMENT.md
         | 
| 67 | 
            -
            - Gemfile
         | 
| 68 25 | 
             
            - History.md
         | 
| 69 26 | 
             
            - LICENSE
         | 
| 70 | 
            -
            - Manifest.txt
         | 
| 71 27 | 
             
            - README.md
         | 
| 72 | 
            -
            - Rakefile
         | 
| 73 | 
            -
            - Release.md
         | 
| 74 28 | 
             
            - bin/puma
         | 
| 75 29 | 
             
            - bin/puma-wild
         | 
| 76 30 | 
             
            - bin/pumactl
         | 
| 77 31 | 
             
            - docs/nginx.md
         | 
| 32 | 
            +
            - docs/plugins.md
         | 
| 33 | 
            +
            - docs/restart.md
         | 
| 78 34 | 
             
            - docs/signals.md
         | 
| 79 35 | 
             
            - docs/systemd.md
         | 
| 80 36 | 
             
            - ext/puma_http11/PumaHttp11Service.java
         | 
| @@ -91,7 +47,6 @@ files: | |
| 91 47 | 
             
            - ext/puma_http11/org/jruby/puma/Http11Parser.java
         | 
| 92 48 | 
             
            - ext/puma_http11/org/jruby/puma/MiniSSL.java
         | 
| 93 49 | 
             
            - ext/puma_http11/puma_http11.c
         | 
| 94 | 
            -
            - gemfiles/2.1-Gemfile
         | 
| 95 50 | 
             
            - lib/puma.rb
         | 
| 96 51 | 
             
            - lib/puma/accept_nonblock.rb
         | 
| 97 52 | 
             
            - lib/puma/app/status.rb
         | 
| @@ -132,7 +87,6 @@ files: | |
| 132 87 | 
             
            - lib/puma/thread_pool.rb
         | 
| 133 88 | 
             
            - lib/puma/util.rb
         | 
| 134 89 | 
             
            - lib/rack/handler/puma.rb
         | 
| 135 | 
            -
            - puma.gemspec
         | 
| 136 90 | 
             
            - tools/jungle/README.md
         | 
| 137 91 | 
             
            - tools/jungle/init.d/README.md
         | 
| 138 92 | 
             
            - tools/jungle/init.d/puma
         | 
| @@ -146,9 +100,7 @@ licenses: | |
| 146 100 | 
             
            - BSD-3-Clause
         | 
| 147 101 | 
             
            metadata: {}
         | 
| 148 102 | 
             
            post_install_message:
         | 
| 149 | 
            -
            rdoc_options:
         | 
| 150 | 
            -
            - "--main"
         | 
| 151 | 
            -
            - README.md
         | 
| 103 | 
            +
            rdoc_options: []
         | 
| 152 104 | 
             
            require_paths:
         | 
| 153 105 | 
             
            - lib
         | 
| 154 106 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
    
        data/.github/issue_template.md
    DELETED
    
    | @@ -1,20 +0,0 @@ | |
| 1 | 
            -
            ### Steps to reproduce
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            1) ...
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            2) ...
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            3) ...
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            ### Expected behavior
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            Tell us what should happen ...
         | 
| 12 | 
            -
             | 
| 13 | 
            -
            ### Actual behavior
         | 
| 14 | 
            -
             | 
| 15 | 
            -
            Tell us what happens instead ...
         | 
| 16 | 
            -
             | 
| 17 | 
            -
            ### System configuration
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            **Ruby version**:
         | 
| 20 | 
            -
            **Rails version**:
         | 
    
        data/DEPLOYMENT.md
    DELETED
    
    | @@ -1,91 +0,0 @@ | |
| 1 | 
            -
            # Deployment engineering for puma
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            Puma is software that is expected to be run in a deployed environment eventually.
         | 
| 4 | 
            -
            You can certainly use it as your dev server only, but most people look to use
         | 
| 5 | 
            -
            it in their production deployments as well.
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            To that end, this is meant to serve as a foundation of wisdom how to do that
         | 
| 8 | 
            -
            in a way that increases happiness and decreases downtime.
         | 
| 9 | 
            -
             | 
| 10 | 
            -
            ## Specifying puma
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            Most people want to do this by putting `gem "puma"` into their Gemfile, so we'll
         | 
| 13 | 
            -
            go ahead and assume that. Go add it now... we'll wait.
         | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
            Welcome back!
         | 
| 17 | 
            -
             | 
| 18 | 
            -
            ## Single vs Cluster mode
         | 
| 19 | 
            -
             | 
| 20 | 
            -
            Puma was originally conceived as a thread-only webserver, but grew the ability to
         | 
| 21 | 
            -
            also use processes in version 2.
         | 
| 22 | 
            -
             | 
| 23 | 
            -
            Here are some rules of thumb:
         | 
| 24 | 
            -
             | 
| 25 | 
            -
            ### MRI
         | 
| 26 | 
            -
             | 
| 27 | 
            -
            * Use cluster mode and set the number of workers to 1.5x the number of cpu cores
         | 
| 28 | 
            -
              in the machine, minimum 2.
         | 
| 29 | 
            -
            * Set the number of threads to desired concurrent requests / number of workers.
         | 
| 30 | 
            -
              Puma defaults to 16 and that's a decent number.
         | 
| 31 | 
            -
             | 
| 32 | 
            -
            #### Migrating from Unicorn
         | 
| 33 | 
            -
             | 
| 34 | 
            -
            * If you're migrating from unicorn though, here are some settings to start with:
         | 
| 35 | 
            -
              * Set workers to half the number of unicorn workers you're using
         | 
| 36 | 
            -
              * Set threads to 2
         | 
| 37 | 
            -
              * Enjoy 50% memory savings
         | 
| 38 | 
            -
            * As you grow more confident in the thread safety of your app, you can tune the
         | 
| 39 | 
            -
              workers down and the threads up.
         | 
| 40 | 
            -
             | 
| 41 | 
            -
            #### Worker utilization
         | 
| 42 | 
            -
             | 
| 43 | 
            -
            **How do you know if you're got enough (or too many workers)?**
         | 
| 44 | 
            -
             | 
| 45 | 
            -
            A good question. Due to MRI's GIL, only one thread can be executing Ruby code at a time.
         | 
| 46 | 
            -
            But since so many apps are waiting on IO from DBs, etc., they can utilize threads
         | 
| 47 | 
            -
            to make better use of the process.
         | 
| 48 | 
            -
             | 
| 49 | 
            -
            The rule of thumb is you never want processes that are pegged all the time. This
         | 
| 50 | 
            -
            means that there is more work to do that the process can get through. On the other
         | 
| 51 | 
            -
            hand, if you have processes that sit around doing nothing, then they're just eating
         | 
| 52 | 
            -
            up resources.
         | 
| 53 | 
            -
             | 
| 54 | 
            -
            Watching your CPU utilization over time and aim for about 70% on average. This means
         | 
| 55 | 
            -
            you've got capacity still but aren't starving threads.
         | 
| 56 | 
            -
             | 
| 57 | 
            -
            ## Daemonizing
         | 
| 58 | 
            -
             | 
| 59 | 
            -
            I prefer to not daemonize my servers and use something like `runit` or `upstart` to
         | 
| 60 | 
            -
            monitor them as child processes. This gives them fast response to crashes and
         | 
| 61 | 
            -
            makes it easy to figure out what is going on. Additionally, unlike `unicorn`,
         | 
| 62 | 
            -
            puma does not require daemonization to do zero-downtime restarts.
         | 
| 63 | 
            -
             | 
| 64 | 
            -
            I see people using daemonization because they start puma directly via capistrano
         | 
| 65 | 
            -
            task and thus want it to live on past the `cap deploy`. To this people I said:
         | 
| 66 | 
            -
            You need to be using a process monitor. Nothing is making sure puma stays up in
         | 
| 67 | 
            -
            this scenario! You're just waiting for something weird to happen, puma to die,
         | 
| 68 | 
            -
            and to get paged at 3am. Do yourself a favor, at least the process monitoring
         | 
| 69 | 
            -
            your OS comes with, be it `sysvinit`, `upstart`, or `systemd`. Or branch out
         | 
| 70 | 
            -
            and use `runit` or hell, even `monit`.
         | 
| 71 | 
            -
             | 
| 72 | 
            -
            ## Restarting
         | 
| 73 | 
            -
             | 
| 74 | 
            -
            You probably will want to deploy some new code at some point, and you'd like
         | 
| 75 | 
            -
            puma to start running that new code. Minimizing the amount of time the server
         | 
| 76 | 
            -
            is unavailable would be nice as well. Here's how to do it:
         | 
| 77 | 
            -
             | 
| 78 | 
            -
            1. Don't use `preload!`. This dirties the master process and means it will have
         | 
| 79 | 
            -
            to shutdown all the workers and re-exec itself to get your new code. It is not compatible with phased-restart and `prune_bundler` as well.
         | 
| 80 | 
            -
             | 
| 81 | 
            -
            1. Use `prune_bundler`. This makes it so that the cluster master will detach itself
         | 
| 82 | 
            -
            from a Bundler context on start. This allows the cluster workers to load your app
         | 
| 83 | 
            -
            and start a brand new Bundler context within the worker only. This means your
         | 
| 84 | 
            -
            master remains pristine and can live on between new releases of your code.
         | 
| 85 | 
            -
             | 
| 86 | 
            -
            1. Use phased-restart (`SIGUSR1` or `pumactl phased-restart`). This tells the master
         | 
| 87 | 
            -
            to kill off one worker at a time and restart them in your new code. This minimizes
         | 
| 88 | 
            -
            downtime and staggers the restart nicely. **WARNING** This means that both your
         | 
| 89 | 
            -
            old code and your new code will be running concurrently. Most deployment solutions
         | 
| 90 | 
            -
            already cause that, but it's worth warning you about it again. Be careful with your
         | 
| 91 | 
            -
            migrations, etc!
         |