puma 6.0.0 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +60 -5
- data/README.md +1 -0
- data/docs/nginx.md +1 -1
- data/docs/systemd.md +1 -2
- data/lib/puma/binder.rb +4 -3
- data/lib/puma/client.rb +32 -4
- data/lib/puma/cluster/worker.rb +5 -0
- data/lib/puma/cluster.rb +5 -5
- data/lib/puma/configuration.rb +1 -0
- data/lib/puma/const.rb +76 -84
- data/lib/puma/dsl.rb +18 -1
- data/lib/puma/io_buffer.rb +10 -0
- data/lib/puma/launcher.rb +4 -22
- data/lib/puma/log_writer.rb +4 -0
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/rack_default.rb +18 -3
- data/lib/puma/reactor.rb +1 -1
- data/lib/puma/request.rb +154 -106
- data/lib/puma/runner.rb +11 -0
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +6 -7
- data/lib/puma/single.rb +3 -1
- data/lib/puma/thread_pool.rb +1 -4
- data/lib/puma.rb +1 -3
- data/lib/rack/handler/puma.rb +116 -94
- metadata +4 -3
- data/lib/puma/systemd.rb +0 -47
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "socket"
|
4
|
+
|
5
|
+
module Puma
|
6
|
+
# The MIT License
|
7
|
+
#
|
8
|
+
# Copyright (c) 2017-2022 Agis Anastasopoulos
|
9
|
+
#
|
10
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
11
|
+
# this software and associated documentation files (the "Software"), to deal in
|
12
|
+
# the Software without restriction, including without limitation the rights to
|
13
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
14
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
15
|
+
# subject to the following conditions:
|
16
|
+
#
|
17
|
+
# The above copyright notice and this permission notice shall be included in all
|
18
|
+
# copies or substantial portions of the Software.
|
19
|
+
#
|
20
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
22
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
23
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
24
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
25
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
#
|
27
|
+
# This is a copy of https://github.com/agis/ruby-sdnotify as of commit cca575c
|
28
|
+
# The only changes made was "rehoming" it within the Puma module to avoid
|
29
|
+
# namespace collisions and applying standard's code formatting style.
|
30
|
+
#
|
31
|
+
# SdNotify is a pure-Ruby implementation of sd_notify(3). It can be used to
|
32
|
+
# notify systemd about state changes. Methods of this package are no-op on
|
33
|
+
# non-systemd systems (eg. Darwin).
|
34
|
+
#
|
35
|
+
# The API maps closely to the original implementation of sd_notify(3),
|
36
|
+
# therefore be sure to check the official man pages prior to using SdNotify.
|
37
|
+
#
|
38
|
+
# @see https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
39
|
+
module SdNotify
|
40
|
+
# Exception raised when there's an error writing to the notification socket
|
41
|
+
class NotifyError < RuntimeError; end
|
42
|
+
|
43
|
+
READY = "READY=1"
|
44
|
+
RELOADING = "RELOADING=1"
|
45
|
+
STOPPING = "STOPPING=1"
|
46
|
+
STATUS = "STATUS="
|
47
|
+
ERRNO = "ERRNO="
|
48
|
+
MAINPID = "MAINPID="
|
49
|
+
WATCHDOG = "WATCHDOG=1"
|
50
|
+
FDSTORE = "FDSTORE=1"
|
51
|
+
|
52
|
+
def self.ready(unset_env=false)
|
53
|
+
notify(READY, unset_env)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.reloading(unset_env=false)
|
57
|
+
notify(RELOADING, unset_env)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.stopping(unset_env=false)
|
61
|
+
notify(STOPPING, unset_env)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param status [String] a custom status string that describes the current
|
65
|
+
# state of the service
|
66
|
+
def self.status(status, unset_env=false)
|
67
|
+
notify("#{STATUS}#{status}", unset_env)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param errno [Integer]
|
71
|
+
def self.errno(errno, unset_env=false)
|
72
|
+
notify("#{ERRNO}#{errno}", unset_env)
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param pid [Integer]
|
76
|
+
def self.mainpid(pid, unset_env=false)
|
77
|
+
notify("#{MAINPID}#{pid}", unset_env)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.watchdog(unset_env=false)
|
81
|
+
notify(WATCHDOG, unset_env)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.fdstore(unset_env=false)
|
85
|
+
notify(FDSTORE, unset_env)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param [Boolean] true if the service manager expects watchdog keep-alive
|
89
|
+
# notification messages to be sent from this process.
|
90
|
+
#
|
91
|
+
# If the $WATCHDOG_USEC environment variable is set,
|
92
|
+
# and the $WATCHDOG_PID variable is unset or set to the PID of the current
|
93
|
+
# process
|
94
|
+
#
|
95
|
+
# @note Unlike sd_watchdog_enabled(3), this method does not mutate the
|
96
|
+
# environment.
|
97
|
+
def self.watchdog?
|
98
|
+
wd_usec = ENV["WATCHDOG_USEC"]
|
99
|
+
wd_pid = ENV["WATCHDOG_PID"]
|
100
|
+
|
101
|
+
return false if !wd_usec
|
102
|
+
|
103
|
+
begin
|
104
|
+
wd_usec = Integer(wd_usec)
|
105
|
+
rescue
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
|
109
|
+
return false if wd_usec <= 0
|
110
|
+
return true if !wd_pid || wd_pid == $$.to_s
|
111
|
+
|
112
|
+
false
|
113
|
+
end
|
114
|
+
|
115
|
+
# Notify systemd with the provided state, via the notification socket, if
|
116
|
+
# any.
|
117
|
+
#
|
118
|
+
# Generally this method will be used indirectly through the other methods
|
119
|
+
# of the library.
|
120
|
+
#
|
121
|
+
# @param state [String]
|
122
|
+
# @param unset_env [Boolean]
|
123
|
+
#
|
124
|
+
# @return [Fixnum, nil] the number of bytes written to the notification
|
125
|
+
# socket or nil if there was no socket to report to (eg. the program wasn't
|
126
|
+
# started by systemd)
|
127
|
+
#
|
128
|
+
# @raise [NotifyError] if there was an error communicating with the systemd
|
129
|
+
# socket
|
130
|
+
#
|
131
|
+
# @see https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
132
|
+
def self.notify(state, unset_env=false)
|
133
|
+
sock = ENV["NOTIFY_SOCKET"]
|
134
|
+
|
135
|
+
return nil if !sock
|
136
|
+
|
137
|
+
ENV.delete("NOTIFY_SOCKET") if unset_env
|
138
|
+
|
139
|
+
begin
|
140
|
+
Addrinfo.unix(sock, :DGRAM).connect do |s|
|
141
|
+
s.close_on_exec = true
|
142
|
+
s.write(state)
|
143
|
+
end
|
144
|
+
rescue StandardError => e
|
145
|
+
raise NotifyError, "#{e.class}: #{e.message}", e.backtrace
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/puma/server.rb
CHANGED
@@ -11,7 +11,6 @@ require_relative 'reactor'
|
|
11
11
|
require_relative 'client'
|
12
12
|
require_relative 'binder'
|
13
13
|
require_relative 'util'
|
14
|
-
require_relative 'io_buffer'
|
15
14
|
require_relative 'request'
|
16
15
|
|
17
16
|
require 'socket'
|
@@ -96,6 +95,7 @@ module Puma
|
|
96
95
|
@queue_requests = @options[:queue_requests]
|
97
96
|
@max_fast_inline = @options[:max_fast_inline]
|
98
97
|
@io_selector_backend = @options[:io_selector_backend]
|
98
|
+
@http_content_length_limit = @options[:http_content_length_limit]
|
99
99
|
|
100
100
|
temp = !!(@options[:environment] =~ /\A(development|test)\z/)
|
101
101
|
@leak_stack_on_error = @options[:environment] ? temp : true
|
@@ -230,7 +230,7 @@ module Puma
|
|
230
230
|
|
231
231
|
@status = :run
|
232
232
|
|
233
|
-
@thread_pool = ThreadPool.new(thread_name, @options) { |
|
233
|
+
@thread_pool = ThreadPool.new(thread_name, @options) { |client| process_client client }
|
234
234
|
|
235
235
|
if @queue_requests
|
236
236
|
@reactor = Reactor.new(@io_selector_backend) { |c| reactor_wakeup c }
|
@@ -335,6 +335,7 @@ module Puma
|
|
335
335
|
drain += 1 if shutting_down?
|
336
336
|
pool << Client.new(io, @binder.env(sock)).tap { |c|
|
337
337
|
c.listener = sock
|
338
|
+
c.http_content_length_limit = @http_content_length_limit
|
338
339
|
c.send(addr_send_name, addr_value) if addr_value
|
339
340
|
}
|
340
341
|
end
|
@@ -401,7 +402,7 @@ module Puma
|
|
401
402
|
# returning.
|
402
403
|
#
|
403
404
|
# Return true if one or more requests were processed.
|
404
|
-
def process_client(client
|
405
|
+
def process_client(client)
|
405
406
|
# Advertise this server into the thread
|
406
407
|
Thread.current[ThreadLocalKey] = self
|
407
408
|
|
@@ -427,15 +428,13 @@ module Puma
|
|
427
428
|
|
428
429
|
while true
|
429
430
|
@requests_count += 1
|
430
|
-
case handle_request(client,
|
431
|
+
case handle_request(client, requests + 1)
|
431
432
|
when false
|
432
433
|
break
|
433
434
|
when :async
|
434
435
|
close_socket = false
|
435
436
|
break
|
436
437
|
when true
|
437
|
-
buffer.reset
|
438
|
-
|
439
438
|
ThreadPool.clean_thread_locals if clean_thread_locals
|
440
439
|
|
441
440
|
requests += 1
|
@@ -469,7 +468,7 @@ module Puma
|
|
469
468
|
# The ensure tries to close +client+ down
|
470
469
|
requests > 0
|
471
470
|
ensure
|
472
|
-
|
471
|
+
client.io_buffer.reset
|
473
472
|
|
474
473
|
begin
|
475
474
|
client.close if close_socket
|
data/lib/puma/single.rb
CHANGED
@@ -16,7 +16,7 @@ module Puma
|
|
16
16
|
# @!attribute [r] stats
|
17
17
|
def stats
|
18
18
|
{
|
19
|
-
started_at: @started_at
|
19
|
+
started_at: utc_iso8601(@started_at)
|
20
20
|
}.merge(@server.stats).merge(super)
|
21
21
|
end
|
22
22
|
|
@@ -57,6 +57,8 @@ module Puma
|
|
57
57
|
|
58
58
|
@events.fire_on_booted!
|
59
59
|
|
60
|
+
debug_loaded_extensions("Loaded Extensions:") if @log_writer.debug?
|
61
|
+
|
60
62
|
begin
|
61
63
|
server_thread.join
|
62
64
|
rescue Interrupt
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -45,7 +45,6 @@ module Puma
|
|
45
45
|
@min = Integer(options[:min_threads])
|
46
46
|
@max = Integer(options[:max_threads])
|
47
47
|
@block = block
|
48
|
-
@extra = [::Puma::IOBuffer]
|
49
48
|
@out_of_band = options[:out_of_band]
|
50
49
|
@clean_thread_locals = options[:clean_thread_locals]
|
51
50
|
@reaping_time = options[:reaping_time]
|
@@ -112,8 +111,6 @@ module Puma
|
|
112
111
|
not_empty = @not_empty
|
113
112
|
not_full = @not_full
|
114
113
|
|
115
|
-
extra = @extra.map { |i| i.new }
|
116
|
-
|
117
114
|
while true
|
118
115
|
work = nil
|
119
116
|
|
@@ -147,7 +144,7 @@ module Puma
|
|
147
144
|
end
|
148
145
|
|
149
146
|
begin
|
150
|
-
@out_of_band_pending = true if block.call(work
|
147
|
+
@out_of_band_pending = true if block.call(work)
|
151
148
|
rescue Exception => e
|
152
149
|
STDERR.puts "Error reached top of thread-pool: #{e.message} (#{e.class})"
|
153
150
|
end
|
data/lib/puma.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
# Standard libraries
|
4
4
|
require 'socket'
|
5
5
|
require 'tempfile'
|
6
|
-
require 'time'
|
7
|
-
require 'etc'
|
8
6
|
require 'uri'
|
9
7
|
require 'stringio'
|
10
8
|
|
@@ -28,7 +26,7 @@ module Puma
|
|
28
26
|
# not in minissl.rb
|
29
27
|
HAS_SSL = const_defined?(:MiniSSL, false) && MiniSSL.const_defined?(:Engine, false)
|
30
28
|
|
31
|
-
HAS_UNIX_SOCKET = Object.const_defined?
|
29
|
+
HAS_UNIX_SOCKET = Object.const_defined?(:UNIXSocket) && !IS_WINDOWS
|
32
30
|
|
33
31
|
if HAS_SSL
|
34
32
|
require_relative 'puma/minissl'
|
data/lib/rack/handler/puma.rb
CHANGED
@@ -1,114 +1,136 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
(options.keys - user_supplied_options).each do |k|
|
28
|
-
default_options[k] = options.delete(k)
|
29
|
-
end
|
3
|
+
# This module is used as an 'include' file in code at bottom of file
|
4
|
+
module Puma
|
5
|
+
module RackHandler
|
6
|
+
DEFAULT_OPTIONS = {
|
7
|
+
:Verbose => false,
|
8
|
+
:Silent => false
|
9
|
+
}
|
10
|
+
|
11
|
+
def config(app, options = {})
|
12
|
+
require_relative '../../puma'
|
13
|
+
require_relative '../../puma/configuration'
|
14
|
+
require_relative '../../puma/log_writer'
|
15
|
+
require_relative '../../puma/launcher'
|
16
|
+
|
17
|
+
default_options = DEFAULT_OPTIONS.dup
|
18
|
+
|
19
|
+
# Libraries pass in values such as :Port and there is no way to determine
|
20
|
+
# if it is a default provided by the library or a special value provided
|
21
|
+
# by the user. A special key `user_supplied_options` can be passed. This
|
22
|
+
# contains an array of all explicitly defined user options. We then
|
23
|
+
# know that all other values are defaults
|
24
|
+
if user_supplied_options = options.delete(:user_supplied_options)
|
25
|
+
(options.keys - user_supplied_options).each do |k|
|
26
|
+
default_options[k] = options.delete(k)
|
30
27
|
end
|
28
|
+
end
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
if options[:environment]
|
39
|
-
user_config.environment options[:environment]
|
40
|
-
end
|
41
|
-
|
42
|
-
if options[:Threads]
|
43
|
-
min, max = options.delete(:Threads).split(':', 2)
|
44
|
-
user_config.threads min, max
|
45
|
-
end
|
46
|
-
|
47
|
-
if options[:Host] || options[:Port]
|
48
|
-
host = options[:Host] || default_options[:Host]
|
49
|
-
port = options[:Port] || default_options[:Port]
|
50
|
-
self.set_host_port_to_config(host, port, user_config)
|
51
|
-
end
|
52
|
-
|
53
|
-
if default_options[:Host]
|
54
|
-
file_config.set_default_host(default_options[:Host])
|
55
|
-
end
|
56
|
-
self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
|
57
|
-
|
58
|
-
user_config.app app
|
30
|
+
conf = ::Puma::Configuration.new(options, default_options) do |user_config, file_config, default_config|
|
31
|
+
if options.delete(:Verbose)
|
32
|
+
require 'rack/common_logger'
|
33
|
+
app = Rack::CommonLogger.new(app, STDOUT)
|
59
34
|
end
|
60
|
-
conf
|
61
|
-
end
|
62
35
|
|
63
|
-
|
64
|
-
|
36
|
+
if options[:environment]
|
37
|
+
user_config.environment options[:environment]
|
38
|
+
end
|
65
39
|
|
66
|
-
|
40
|
+
if options[:Threads]
|
41
|
+
min, max = options.delete(:Threads).split(':', 2)
|
42
|
+
user_config.threads min, max
|
43
|
+
end
|
67
44
|
|
68
|
-
|
45
|
+
if options[:Host] || options[:Port]
|
46
|
+
host = options[:Host] || default_options[:Host]
|
47
|
+
port = options[:Port] || default_options[:Port]
|
48
|
+
self.set_host_port_to_config(host, port, user_config)
|
49
|
+
end
|
69
50
|
|
70
|
-
|
71
|
-
|
72
|
-
launcher.run
|
73
|
-
rescue Interrupt
|
74
|
-
puts "* Gracefully stopping, waiting for requests to finish"
|
75
|
-
launcher.stop
|
76
|
-
puts "* Goodbye!"
|
51
|
+
if default_options[:Host]
|
52
|
+
file_config.set_default_host(default_options[:Host])
|
77
53
|
end
|
54
|
+
self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
|
55
|
+
|
56
|
+
user_config.app app
|
78
57
|
end
|
58
|
+
conf
|
59
|
+
end
|
60
|
+
|
61
|
+
def run(app, **options)
|
62
|
+
conf = self.config(app, options)
|
63
|
+
|
64
|
+
log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
|
65
|
+
|
66
|
+
launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer)
|
79
67
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
68
|
+
yield launcher if block_given?
|
69
|
+
begin
|
70
|
+
launcher.run
|
71
|
+
rescue Interrupt
|
72
|
+
puts "* Gracefully stopping, waiting for requests to finish"
|
73
|
+
launcher.stop
|
74
|
+
puts "* Goodbye!"
|
87
75
|
end
|
76
|
+
end
|
88
77
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
78
|
+
def valid_options
|
79
|
+
{
|
80
|
+
"Host=HOST" => "Hostname to listen on (default: localhost)",
|
81
|
+
"Port=PORT" => "Port to listen on (default: 8080)",
|
82
|
+
"Threads=MIN:MAX" => "min:max threads to use (default 0:16)",
|
83
|
+
"Verbose" => "Don't report each request (default: false)"
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_host_port_to_config(host, port, config)
|
88
|
+
config.clear_binds! if host || port
|
89
|
+
|
90
|
+
if host && (host[0,1] == '.' || host[0,1] == '/')
|
91
|
+
config.bind "unix://#{host}"
|
92
|
+
elsif host && host =~ /^ssl:\/\//
|
93
|
+
uri = URI.parse(host)
|
94
|
+
uri.port ||= port || ::Puma::Configuration::DEFAULTS[:tcp_port]
|
95
|
+
config.bind uri.to_s
|
96
|
+
else
|
97
|
+
|
98
|
+
if host
|
99
|
+
port ||= ::Puma::Configuration::DEFAULTS[:tcp_port]
|
100
|
+
end
|
101
|
+
|
102
|
+
if port
|
103
|
+
host ||= ::Puma::Configuration::DEFAULTS[:tcp_host]
|
104
|
+
config.port port, host
|
108
105
|
end
|
109
106
|
end
|
110
107
|
end
|
108
|
+
end
|
109
|
+
end
|
111
110
|
|
112
|
-
|
111
|
+
# rackup was removed in Rack 3, it is now a separate gem
|
112
|
+
if Object.const_defined? :Rackup
|
113
|
+
module Rackup
|
114
|
+
module Handler
|
115
|
+
module Puma
|
116
|
+
class << self
|
117
|
+
include ::Puma::RackHandler
|
118
|
+
end
|
119
|
+
end
|
120
|
+
register :puma, Puma
|
121
|
+
end
|
122
|
+
end
|
123
|
+
elsif Object.const_defined?(:Rack) && Rack::RELEASE < '3'
|
124
|
+
module Rack
|
125
|
+
module Handler
|
126
|
+
module Puma
|
127
|
+
class << self
|
128
|
+
include ::Puma::RackHandler
|
129
|
+
end
|
130
|
+
end
|
131
|
+
register :puma, Puma
|
132
|
+
end
|
113
133
|
end
|
134
|
+
else
|
135
|
+
raise "You must install the rackup gem when using Rack 3"
|
114
136
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/puma/minissl/context_builder.rb
|
105
105
|
- lib/puma/null_io.rb
|
106
106
|
- lib/puma/plugin.rb
|
107
|
+
- lib/puma/plugin/systemd.rb
|
107
108
|
- lib/puma/plugin/tmp_restart.rb
|
108
109
|
- lib/puma/rack/builder.rb
|
109
110
|
- lib/puma/rack/urlmap.rb
|
@@ -111,10 +112,10 @@ files:
|
|
111
112
|
- lib/puma/reactor.rb
|
112
113
|
- lib/puma/request.rb
|
113
114
|
- lib/puma/runner.rb
|
115
|
+
- lib/puma/sd_notify.rb
|
114
116
|
- lib/puma/server.rb
|
115
117
|
- lib/puma/single.rb
|
116
118
|
- lib/puma/state_file.rb
|
117
|
-
- lib/puma/systemd.rb
|
118
119
|
- lib/puma/thread_pool.rb
|
119
120
|
- lib/puma/util.rb
|
120
121
|
- lib/rack/handler/puma.rb
|
@@ -144,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
145
|
- !ruby/object:Gem::Version
|
145
146
|
version: '0'
|
146
147
|
requirements: []
|
147
|
-
rubygems_version: 3.
|
148
|
+
rubygems_version: 3.3.20
|
148
149
|
signing_key:
|
149
150
|
specification_version: 4
|
150
151
|
summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for
|
data/lib/puma/systemd.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'sd_notify'
|
4
|
-
|
5
|
-
module Puma
|
6
|
-
class Systemd
|
7
|
-
def initialize(log_writer, events)
|
8
|
-
@log_writer = log_writer
|
9
|
-
@events = events
|
10
|
-
end
|
11
|
-
|
12
|
-
def hook_events
|
13
|
-
@events.on_booted { SdNotify.ready }
|
14
|
-
@events.on_stopped { SdNotify.stopping }
|
15
|
-
@events.on_restart { SdNotify.reloading }
|
16
|
-
end
|
17
|
-
|
18
|
-
def start_watchdog
|
19
|
-
return unless SdNotify.watchdog?
|
20
|
-
|
21
|
-
ping_f = watchdog_sleep_time
|
22
|
-
|
23
|
-
log "Pinging systemd watchdog every #{ping_f.round(1)} sec"
|
24
|
-
Thread.new do
|
25
|
-
loop do
|
26
|
-
sleep ping_f
|
27
|
-
SdNotify.watchdog
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def watchdog_sleep_time
|
35
|
-
usec = Integer(ENV["WATCHDOG_USEC"])
|
36
|
-
|
37
|
-
sec_f = usec / 1_000_000.0
|
38
|
-
# "It is recommended that a daemon sends a keep-alive notification message
|
39
|
-
# to the service manager every half of the time returned here."
|
40
|
-
sec_f / 2
|
41
|
-
end
|
42
|
-
|
43
|
-
def log(str)
|
44
|
-
@log_writer.log(str)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|