Hello community, here is the log from the commit of package rubygem-puma for openSUSE:Factory checked in at 2017-12-22 12:18:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-puma (Old) and /work/SRC/openSUSE:Factory/.rubygem-puma.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-puma" Fri Dec 22 12:18:22 2017 rev:28 rq:554630 version:3.11.0 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-puma/rubygem-puma.changes 2017-09-13 22:36:08.286590475 +0200 +++ /work/SRC/openSUSE:Factory/.rubygem-puma.new/rubygem-puma.changes 2017-12-22 12:18:23.367454185 +0100 @@ -1,0 +2,27 @@ +Sun Dec 3 19:29:36 UTC 2017 - [email protected] + +- updated to version 3.11.0 + see installed History.md + + ## 3.11.0 / 2017-11-20 + + * 2 features: + * HTTP 203 Early Hints (#1403) + * 421/451 status codes now have correct status messages attached (#1435) + + * 9 bugfixes: + * Environment config files (/config/puma/<ENV>.rb) load correctly (#1340) + * Specify windows dependencies correctly (#1434, #1436) + * puma/events required in test helper (#1418) + * Correct control CLI's option help text (#1416) + * Remove a warning for unused variable in mini_ssl (#1409) + * Correct pumactl docs argument ordering (#1427) + * Fix an uninitialized variable warning in server.rb (#1430) + * Fix docs typo/error in Launcher init (#1429) + * Deal with leading spaces in RUBYOPT (#1455) + + * 2 other: + * Add docs about internals (#1425, #1452) + * Tons of test fixes from @MSP-Greg (#1439, #1442, #1464) + +------------------------------------------------------------------- Old: ---- puma-3.10.0.gem New: ---- puma-3.11.0.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-puma.spec ++++++ --- /var/tmp/diff_new_pack.MyGKeq/_old 2017-12-22 12:18:24.067420055 +0100 +++ /var/tmp/diff_new_pack.MyGKeq/_new 2017-12-22 12:18:24.067420055 +0100 @@ -24,7 +24,7 @@ # Name: rubygem-puma -Version: 3.10.0 +Version: 3.11.0 Release: 0 %define mod_name puma %define mod_full_name %{mod_name}-%{version} ++++++ puma-3.10.0.gem -> puma-3.11.0.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/History.md new/History.md --- old/History.md 2017-08-17 21:18:29.000000000 +0200 +++ new/History.md 2017-11-20 17:26:13.000000000 +0100 @@ -1,3 +1,24 @@ +## 3.11.0 / 2017-11-20 + +* 2 features: + * HTTP 203 Early Hints (#1403) + * 421/451 status codes now have correct status messages attached (#1435) + +* 9 bugfixes: + * Environment config files (/config/puma/<ENV>.rb) load correctly (#1340) + * Specify windows dependencies correctly (#1434, #1436) + * puma/events required in test helper (#1418) + * Correct control CLI's option help text (#1416) + * Remove a warning for unused variable in mini_ssl (#1409) + * Correct pumactl docs argument ordering (#1427) + * Fix an uninitialized variable warning in server.rb (#1430) + * Fix docs typo/error in Launcher init (#1429) + * Deal with leading spaces in RUBYOPT (#1455) + +* 2 other: + * Add docs about internals (#1425, #1452) + * Tons of test fixes from @MSP-Greg (#1439, #1442, #1464) + ## 3.10.0 / 2017-08-17 * 3 features: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.md new/README.md --- old/README.md 2017-08-17 21:18:29.000000000 +0200 +++ new/README.md 2017-11-20 17:26:13.000000000 +0100 @@ -74,6 +74,8 @@ Puma will automatically scale the number of threads, from the minimum until it caps out at the maximum, based on how much traffic is present. The current default is `0:16`. Feel free to experiment, but be careful not to set the number of maximum threads to a large number, as you may exhaust resources on the system (or hit resource limits). +Be aware that additionally Puma creates threads on its own for internal purposes (e.g. handling slow clients). So even if you specify -t 1:1, expect around 7 threads created in your application. + ### Clustered mode Puma also offers "clustered mode". Clustered mode `fork`s workers from a master process. Each child process still has its own thread pool. You can tune the number of workers with the `-w` (or `--workers`) flag: @@ -173,7 +175,7 @@ You can also interact with the control server via `pumactl`. This command will restart Puma: ``` -$ pumactl restart --control-token foo +$ pumactl -C 'tcp://127.0.0.1:9293' --control-token foo restart ``` To see a list of `pumactl` options, use `pumactl --help`. @@ -215,11 +217,14 @@ ## Known Bugs -For MRI versions 2.2.7, 2.3.4 and 2.4.1, you may see ```stream closed in another thread (IOError)```. It may be caused by a [Ruby bug](https://bugs.ruby-lang.org/issues/13632). It can be fixed with the gem https://rubygems.org/gems/stopgap_13632: +For MRI versions 2.2.7, 2.2.8, 2.3.4 and 2.4.1, you may see ```stream closed in another thread (IOError)```. It may be caused by a [Ruby bug](https://bugs.ruby-lang.org/issues/13632). It can be fixed with the gem https://rubygems.org/gems/stopgap_13632: ```ruby -if %w(2.2.7 2.3.4 2.4.1).include? RUBY_VERSION - gem "stopgap_13632", "~> 1.0", :platforms => ["mri", "mingw", "x64_mingw"] +if %w(2.2.7 2.2.8 2.3.4 2.4.1).include? RUBY_VERSION + begin + require 'stopgap_13632' + rescue LoadError + end end ``` Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docs/architecture.md new/docs/architecture.md --- old/docs/architecture.md 1970-01-01 01:00:00.000000000 +0100 +++ new/docs/architecture.md 2017-11-20 17:26:13.000000000 +0100 @@ -0,0 +1,36 @@ +# Architecture + +## Overview + + + +Puma is a threaded web server, processing requests across a TCP or UNIX socket. + +Workers accept connections from the socket and a thread in the worker's thread pool processes the client's request. + +Clustered mode is shown/discussed here. Single mode is analogous to having a single worker process. + +## Connection pipeline + + + +* Upon startup, Puma listens on a TCP or UNIX socket. + * The backlog of this socket is configured (with a default of 1024), determining how many established but unaccepted connections can exist concurrently. + * This socket backlog is distinct from the "backlog" of work as reported by the control server stats. The latter is the number of connections in that worker's "todo" set waiting for a worker thread. +* By default, a single, separate thread is used to receive HTTP requests across the socket. + * When at least one worker thread is available for work, a connection is accepted and placed in this request buffer + * This thread waits for entire HTTP requests to be received over the connection + * Once received, the connection is pushed into the "todo" set +* Worker threads pop work off the "todo" set for processing + * The thread processes the request via the rack application (which generates the HTTP response) + * The thread writes the response to the connection + * Finally, the thread become available to process another connection in the "todo" set + +### Disabling `queue_requests` + + + +The `queue_requests` option is `true` by default, enabling the separate thread used to buffer requests as described above. + +If set to `false`, this buffer will not be used for connections while waiting for the request to arrive. +In this mode, when a connection is accepted, it is added to the "todo" queue immediately, and a worker will syncronously do any waiting necessarry to read the HTTP request from the socket. \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docs/deployment.md new/docs/deployment.md --- old/docs/deployment.md 1970-01-01 01:00:00.000000000 +0100 +++ new/docs/deployment.md 2017-11-20 17:26:13.000000000 +0100 @@ -0,0 +1,91 @@ +# Deployment engineering for puma + +Puma is software that is expected to be run in a deployed environment eventually. +You can certainly use it as your dev server only, but most people look to use +it in their production deployments as well. + +To that end, this is meant to serve as a foundation of wisdom how to do that +in a way that increases happiness and decreases downtime. + +## Specifying puma + +Most people want to do this by putting `gem "puma"` into their Gemfile, so we'll +go ahead and assume that. Go add it now... we'll wait. + + +Welcome back! + +## Single vs Cluster mode + +Puma was originally conceived as a thread-only webserver, but grew the ability to +also use processes in version 2. + +Here are some rules of thumb: + +### MRI + +* Use cluster mode and set the number of workers to 1.5x the number of cpu cores + in the machine, minimum 2. +* Set the number of threads to desired concurrent requests / number of workers. + Puma defaults to 16 and that's a decent number. + +#### Migrating from Unicorn + +* If you're migrating from unicorn though, here are some settings to start with: + * Set workers to half the number of unicorn workers you're using + * Set threads to 2 + * Enjoy 50% memory savings +* As you grow more confident in the thread safety of your app, you can tune the + workers down and the threads up. + +#### Worker utilization + +**How do you know if you're got enough (or too many workers)?** + +A good question. Due to MRI's GIL, only one thread can be executing Ruby code at a time. +But since so many apps are waiting on IO from DBs, etc., they can utilize threads +to make better use of the process. + +The rule of thumb is you never want processes that are pegged all the time. This +means that there is more work to do that the process can get through. On the other +hand, if you have processes that sit around doing nothing, then they're just eating +up resources. + +Watching your CPU utilization over time and aim for about 70% on average. This means +you've got capacity still but aren't starving threads. + +## Daemonizing + +I prefer to not daemonize my servers and use something like `runit` or `upstart` to +monitor them as child processes. This gives them fast response to crashes and +makes it easy to figure out what is going on. Additionally, unlike `unicorn`, +puma does not require daemonization to do zero-downtime restarts. + +I see people using daemonization because they start puma directly via capistrano +task and thus want it to live on past the `cap deploy`. To this people I said: +You need to be using a process monitor. Nothing is making sure puma stays up in +this scenario! You're just waiting for something weird to happen, puma to die, +and to get paged at 3am. Do yourself a favor, at least the process monitoring +your OS comes with, be it `sysvinit`, `upstart`, or `systemd`. Or branch out +and use `runit` or hell, even `monit`. + +## Restarting + +You probably will want to deploy some new code at some point, and you'd like +puma to start running that new code. Minimizing the amount of time the server +is unavailable would be nice as well. Here's how to do it: + +1. Don't use `preload!`. This dirties the master process and means it will have +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. + +1. Use `prune_bundler`. This makes it so that the cluster master will detach itself +from a Bundler context on start. This allows the cluster workers to load your app +and start a brand new Bundler context within the worker only. This means your +master remains pristine and can live on between new releases of your code. + +1. Use phased-restart (`SIGUSR1` or `pumactl phased-restart`). This tells the master +to kill off one worker at a time and restart them in your new code. This minimizes +downtime and staggers the restart nicely. **WARNING** This means that both your +old code and your new code will be running concurrently. Most deployment solutions +already cause that, but it's worth warning you about it again. Be careful with your +migrations, etc! Binary files old/docs/images/puma-connection-flow-no-reactor.png and new/docs/images/puma-connection-flow-no-reactor.png differ Binary files old/docs/images/puma-connection-flow.png and new/docs/images/puma-connection-flow.png differ Binary files old/docs/images/puma-general-arch.png and new/docs/images/puma-general-arch.png differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/puma_http11/mini_ssl.c new/ext/puma_http11/mini_ssl.c --- old/ext/puma_http11/mini_ssl.c 2017-08-17 21:18:29.000000000 +0200 +++ new/ext/puma_http11/mini_ssl.c 2017-11-20 17:26:13.000000000 +0100 @@ -411,6 +411,11 @@ void Init_mini_ssl(VALUE puma) { VALUE mod, eng; +/* Fake operation for documentation (RDoc, YARD) */ +#if 0 == 1 + puma = rb_define_module("Puma"); +#endif + SSL_library_init(); OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); @@ -447,7 +452,7 @@ } void Init_mini_ssl(VALUE puma) { - VALUE mod, eng; + VALUE mod; mod = rb_define_module_under(puma, "MiniSSL"); rb_define_class_under(mod, "SSLError", rb_eStandardError); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/cli.rb new/lib/puma/cli.rb --- old/lib/puma/cli.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/cli.rb 2017-11-20 17:26:13.000000000 +0100 @@ -181,6 +181,10 @@ user_config.tcp_mode! end + o.on "--early-hints", "Enable early hints support" do + user_config.early_hints + end + o.on "-V", "--version", "Print the version information" do puts "puma version #{Puma::Const::VERSION}" exit 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/cluster.rb new/lib/puma/cluster.rb --- old/lib/puma/cluster.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/cluster.rb 2017-11-20 17:26:13.000000000 +0100 @@ -24,7 +24,7 @@ @workers.each { |x| x.term } begin - Process.waitall + @workers.each { |w| Process.waitpid(w.pid) } rescue Interrupt log "! Cancelled waiting for workers" end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/configuration.rb new/lib/puma/configuration.rb --- old/lib/puma/configuration.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/configuration.rb 2017-11-20 17:26:13.000000000 +0100 @@ -189,22 +189,22 @@ end def load + config_files.each { |config_file| @file_dsl._load_from(config_file) } + + @options + end + + def config_files files = @options.all_of(:config_files) - if files.empty? - imp = %W(config/puma/#{@options[:environment]}.rb config/puma.rb).find { |f| - File.exist?(f) - } - - files << imp - elsif files == ["-"] - files = [] - end + return [] if files == ['-'] + return files if files.any? - files.each do |f| - @file_dsl._load_from(f) + first_default_file = %W(config/puma/#{environment_str}.rb config/puma.rb).find do |f| + File.exist?(f) end - @options + + [first_default_file] end # Call once all configuration (included from rackup files) @@ -264,6 +264,10 @@ @options[:environment] end + def environment_str + environment.respond_to?(:call) ? environment.call : environment + end + def load_plugin(name) @plugins.create name end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/const.rb new/lib/puma/const.rb --- old/lib/puma/const.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/const.rb 2017-11-20 17:26:13.000000000 +0100 @@ -54,6 +54,7 @@ 416 => 'Range Not Satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m A Teapot', + 421 => 'Misdirected Request', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', @@ -61,6 +62,7 @@ 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', + 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', @@ -96,8 +98,8 @@ # too taxing on performance. module Const - PUMA_VERSION = VERSION = "3.10.0".freeze - CODE_NAME = "Russell's Teapot".freeze + PUMA_VERSION = VERSION = "3.11.0".freeze + CODE_NAME = "Love Song".freeze PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze FAST_TRACK_KA_TIMEOUT = 0.2 @@ -221,5 +223,7 @@ HIJACK_P = "rack.hijack?".freeze HIJACK = "rack.hijack".freeze HIJACK_IO = "rack.hijack_io".freeze + + EARLY_HINTS = "rack.early_hints".freeze end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/control_cli.rb new/lib/puma/control_cli.rb --- old/lib/puma/control_cli.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/control_cli.rb 2017-11-20 17:26:13.000000000 +0100 @@ -245,7 +245,7 @@ run_args += ["-S", @state] if @state run_args += ["-q"] if @quiet run_args += ["--pidfile", @pidfile] if @pidfile - run_args += ["--control", @control_url] if @control_url + run_args += ["--control-url", @control_url] if @control_url run_args += ["--control-token", @control_auth_token] if @control_auth_token run_args += ["-C", @config_file] if @config_file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/dsl.rb new/lib/puma/dsl.rb --- old/lib/puma/dsl.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/dsl.rb 2017-11-20 17:26:13.000000000 +0100 @@ -241,6 +241,10 @@ @options[:mode] = :tcp end + def early_hints(answer=true) + @options[:early_hints] = answer + end + # Redirect STDOUT and STDERR to files specified. def stdout_redirect(stdout=nil, stderr=nil, append=false) @options[:redirect_stdout] = stdout diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/launcher.rb new/lib/puma/launcher.rb --- old/lib/puma/launcher.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/launcher.rb 2017-11-20 17:26:13.000000000 +0100 @@ -40,7 +40,7 @@ # [200, {}, ["hello world"]] # end # end - # Puma::Launcher.new(conf, argv: Puma::Events.stdio).run + # Puma::Launcher.new(conf, events: Puma::Events.stdio).run def initialize(conf, launcher_args={}) @runner = nil @events = launcher_args[:events] || Events::DEFAULT @@ -168,7 +168,7 @@ env = Bundler::ORIGINAL_ENV.dup # add -rbundler/setup so we load from Gemfile when restarting bundle = "-rbundler/setup" - env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ") unless env["RUBYOPT"].to_s.include?(bundle) + env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle) env else ENV.to_h diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/minissl.rb new/lib/puma/minissl.rb --- old/lib/puma/minissl.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/minissl.rb 2017-11-20 17:26:13.000000000 +0100 @@ -1,3 +1,8 @@ +begin + require 'io/wait' + rescue LoadError +end + module Puma module MiniSSL class Socket @@ -43,7 +48,20 @@ output = engine_read_all return output if output - data = @socket.read_nonblock(size) + begin + data = @socket.read_nonblock(size, exception: false) + if data == :wait_readable || data == :wait_writable + if @socket.to_io.respond_to?(data) + @socket.to_io.__send__(data) + elsif data == :wait_readable + IO.select([@socket.to_io]) + else + IO.select(nil, [@socket.to_io]) + end + else + break + end + end while true @engine.inject(data) output = engine_read_all diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/runner.rb new/lib/puma/runner.rb --- old/lib/puma/runner.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/runner.rb 2017-11-20 17:26:13.000000000 +0100 @@ -161,6 +161,10 @@ server.tcp_mode! end + if @options[:early_hints] + server.early_hints = true + end + unless development? server.leak_stack_on_error = false end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/puma/server.rb new/lib/puma/server.rb --- old/lib/puma/server.rb 2017-08-17 21:18:29.000000000 +0200 +++ new/lib/puma/server.rb 2017-11-20 17:26:13.000000000 +0100 @@ -62,6 +62,7 @@ @thread = nil @thread_pool = nil + @early_hints = nil @persistent_timeout = options.fetch(:persistent_timeout, PERSISTENT_TIMEOUT) @first_data_timeout = options.fetch(:first_data_timeout, FIRST_DATA_TIMEOUT) @@ -81,7 +82,7 @@ @precheck_closing = true end - attr_accessor :binder, :leak_stack_on_error + attr_accessor :binder, :leak_stack_on_error, :early_hints forward :add_tcp_listener, :@binder forward :add_ssl_listener, :@binder @@ -595,6 +596,24 @@ env[RACK_INPUT] = body env[RACK_URL_SCHEME] = env[HTTPS_KEY] ? HTTPS : HTTP + if @early_hints + env[EARLY_HINTS] = lambda { |headers| + fast_write client, "HTTP/1.1 103 Early Hints\r\n".freeze + + headers.each_pair do |k, vs| + if vs.respond_to?(:to_s) && !vs.to_s.empty? + vs.to_s.split(NEWLINE).each do |v| + fast_write client, "#{k}: #{v}\r\n" + end + else + fast_write client, "#{k}: #{v}\r\n" + end + end + + fast_write client, "\r\n".freeze + } + end + # A rack extension. If the app writes #call'ables to this # array, we will invoke them when the request is done. # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2017-08-17 21:18:29.000000000 +0200 +++ new/metadata 2017-11-20 17:26:13.000000000 +0100 @@ -1,14 +1,14 @@ --- !ruby/object:Gem::Specification name: puma version: !ruby/object:Gem::Version - version: 3.10.0 + version: 3.11.0 platform: ruby authors: - Evan Phoenix autorequire: bindir: bin cert_chain: [] -date: 2017-08-17 00:00:00.000000000 Z +date: 2017-11-20 00:00:00.000000000 Z dependencies: [] description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications. Puma is intended for use in both development and production @@ -29,6 +29,11 @@ - bin/puma - bin/puma-wild - bin/pumactl +- docs/architecture.md +- docs/deployment.md +- docs/images/puma-connection-flow-no-reactor.png +- docs/images/puma-connection-flow.png +- docs/images/puma-general-arch.png - docs/nginx.md - docs/plugins.md - docs/restart.md @@ -98,7 +103,8 @@ homepage: http://puma.io licenses: - BSD-3-Clause -metadata: {} +metadata: + msys2_mingw_dependencies: openssl post_install_message: rdoc_options: [] require_paths: @@ -115,7 +121,7 @@ version: '0' requirements: [] rubyforge_project: -rubygems_version: 2.6.11 +rubygems_version: 2.6.13 signing_key: specification_version: 4 summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
