Skip to content

Commit 76f4a6c

Browse files
Fixes Puma 5 implementation
1 parent 88758fd commit 76f4a6c

2 files changed

Lines changed: 48 additions & 23 deletions

File tree

lib/puma/plugin/delayed_stop.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ def start(launcher)
3030
"reserve (e.g. QUIT). Puma reserves: #{PUMA_SIGNALS.map { |s| "SIG#{s}" }.join(', ')}"
3131
end
3232

33+
# Puma 6 renamed `events` to `log_writer` for logging.
34+
logger = launcher.respond_to?(:log_writer) ? launcher.log_writer : launcher.events
35+
3336
Signal.trap(STOP_SIGNAL) do
3437
Thread.new do
35-
launcher.log_writer.log("[delayed_stop] Received SIG#{STOP_SIGNAL}, sleeping #{DRAIN_SECONDS}s before stopping")
38+
logger.log("[delayed_stop] Received SIG#{STOP_SIGNAL}, sleeping #{DRAIN_SECONDS}s before stopping")
3639
sleep(DRAIN_SECONDS)
3740
launcher.stop
3841
end

spec/integration/delayed_stop_spec.rb

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require "tempfile"
4+
35
RSpec.describe "Delayed stop integration", :integration do
46
RACKUP = File.expand_path("../fixtures/config.ru", __dir__)
57

@@ -32,16 +34,28 @@ def wait_for_server_down(port, timeout: 15)
3234
end
3335
end
3436

37+
# Generate a Puma config file that loads the plugin via the DSL,
38+
# which works in both Puma 5 and 6.
39+
def write_puma_config(port:)
40+
file = Tempfile.new(["puma", ".rb"])
41+
file.write(<<~RUBY)
42+
app_dir = "#{File.expand_path('..', __dir__)}"
43+
rackup "\#{app_dir}/fixtures/config.ru"
44+
bind "tcp://127.0.0.1:#{port}"
45+
workers 0
46+
threads 1, 1
47+
plugin :delayed_stop
48+
RUBY
49+
file.close
50+
file
51+
end
52+
3553
def spawn_puma(port:, env_overrides: {})
3654
env = ENV.to_h.merge(env_overrides)
37-
cmd = [
38-
"bundle", "exec", "puma",
39-
"--bind", "tcp://127.0.0.1:#{port}",
40-
"--workers", "0",
41-
"--threads", "1:1",
42-
"--plugin", "delayed_stop",
43-
RACKUP
44-
]
55+
config_file = write_puma_config(port: port)
56+
@tempfiles << config_file
57+
58+
cmd = ["bundle", "exec", "puma", "-C", config_file.path]
4559

4660
stdout_r, stdout_w = IO.pipe
4761
stderr_r, stderr_w = IO.pipe
@@ -53,6 +67,15 @@ def spawn_puma(port:, env_overrides: {})
5367
{ pid: pid, stdout: stdout_r, stderr: stderr_r }
5468
end
5569

70+
def spawn_puma_capture(port:, env_overrides: {})
71+
env = ENV.to_h.merge(env_overrides)
72+
config_file = write_puma_config(port: port)
73+
@tempfiles << config_file
74+
75+
cmd = ["bundle", "exec", "puma", "-C", config_file.path]
76+
Open3.capture3(env, *cmd)
77+
end
78+
5679
def cleanup(handle)
5780
return unless handle
5881

@@ -77,7 +100,12 @@ def wait_for_exit(handle)
77100
handle[:pid] = nil
78101
end
79102

80-
after { cleanup(@handle) }
103+
before { @tempfiles = [] }
104+
105+
after do
106+
cleanup(@handle)
107+
@tempfiles.each(&:unlink)
108+
end
81109

82110
context "when SIGQUIT is received" do
83111
it "keeps the server running during the drain period, then shuts down" do
@@ -156,20 +184,14 @@ def wait_for_exit(handle)
156184
%w[TERM SIGTERM].each do |signal_value|
157185
it "exits with an error when PUMA_DELAYED_STOP_SIGNAL=#{signal_value}" do
158186
port = find_open_port
159-
env = ENV.to_h.merge(
160-
"PUMA_DELAYED_STOP_SIGNAL" => signal_value,
161-
"PUMA_DELAYED_STOP_DRAIN_SECONDS" => "1"
187+
188+
stdout, stderr, status = spawn_puma_capture(
189+
port: port,
190+
env_overrides: {
191+
"PUMA_DELAYED_STOP_SIGNAL" => signal_value,
192+
"PUMA_DELAYED_STOP_DRAIN_SECONDS" => "1"
193+
}
162194
)
163-
cmd = [
164-
"bundle", "exec", "puma",
165-
"--bind", "tcp://127.0.0.1:#{port}",
166-
"--workers", "0",
167-
"--threads", "1:1",
168-
"--plugin", "delayed_stop",
169-
RACKUP
170-
]
171-
172-
stdout, stderr, status = Open3.capture3(env, *cmd)
173195
output = stdout + stderr
174196

175197
expect(status.success?).to be false

0 commit comments

Comments
 (0)