resqued 0.10.1 → 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +4 -0
- data/lib/resqued/listener_pool.rb +5 -0
- data/lib/resqued/master.rb +6 -4
- data/lib/resqued/version.rb +1 -1
- data/spec/integration/master_inherits_child_spec.rb +85 -0
- data/spec/integration/restart_spec.rb +63 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/extra-child-shim +6 -0
- data/spec/support/resqued_path.rb +11 -0
- metadata +10 -4
- data/spec/test_restart.sh +0 -84
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc14cf354d4cd292119aa6e6f06f0c59dd09faf982fe10707e69c5bbb3ef56e4
|
4
|
+
data.tar.gz: 7bad129217778e76f14c1dc6a732025d5cc0bba17baaee9d81ee5a1648768edc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8b5e943ec7612022b8a937c6a380b1d396be6cd2c5ebad13239961232c992dcce54d42e807c1d52f036f102defe4492f4fd498f0299c33e40e5095dc26ab48f
|
7
|
+
data.tar.gz: a26e43be4a408d59d8db061c00b112e45a6fec8b6ba318e145cbac1e53b4087b12f9b2ba3510fa118714aeb8b0117673c90b6f7fb987ca028a8962c85f594e5f
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
Starting with version 0.6.1, resqued uses semantic versioning to indicate incompatibilities between the master process, listener process, and configuration.
|
2
2
|
|
3
|
+
v0.10.2
|
4
|
+
-------
|
5
|
+
* Shut down cleanly even if there are other stray child processes of the master. (#59)
|
6
|
+
|
3
7
|
v0.10.1
|
4
8
|
-------
|
5
9
|
* Avoid deadlock if a listener stops responding. (#58)
|
@@ -25,6 +25,11 @@ module Resqued
|
|
25
25
|
@listener_proxies.size
|
26
26
|
end
|
27
27
|
|
28
|
+
# Public: Are the listeners all gone?
|
29
|
+
def empty?
|
30
|
+
@listener_proxies.empty?
|
31
|
+
end
|
32
|
+
|
28
33
|
# Public: Initialize a new listener, run it, and record it as the current listener. Returns its ListenerProxy.
|
29
34
|
def start!
|
30
35
|
listener_state = ListenerState.new
|
data/lib/resqued/master.rb
CHANGED
@@ -187,7 +187,7 @@ module Resqued
|
|
187
187
|
end
|
188
188
|
|
189
189
|
def reap_all_listeners(waitpid_flags = 0)
|
190
|
-
|
190
|
+
until @listeners.empty?
|
191
191
|
begin
|
192
192
|
lpid, status = Process.waitpid2(-1, waitpid_flags)
|
193
193
|
return unless lpid
|
@@ -203,9 +203,11 @@ module Resqued
|
|
203
203
|
@state.clear_last_good!
|
204
204
|
end
|
205
205
|
|
206
|
-
dead_listener = @listeners.delete(lpid)
|
207
|
-
|
208
|
-
|
206
|
+
if dead_listener = @listeners.delete(lpid)
|
207
|
+
listener_status dead_listener, "stop"
|
208
|
+
dead_listener.dispose
|
209
|
+
end
|
210
|
+
|
209
211
|
write_procline
|
210
212
|
rescue Errno::ECHILD
|
211
213
|
return
|
data/lib/resqued/version.rb
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "timeout"
|
3
|
+
|
4
|
+
describe "Resqued master with an extra child process" do
|
5
|
+
include ResquedPath
|
6
|
+
|
7
|
+
# Starts resqued with an extra child process.
|
8
|
+
def start_resqued_with_extra_child
|
9
|
+
shim_path = File.expand_path("../support/extra-child-shim", File.dirname(__FILE__))
|
10
|
+
|
11
|
+
config_path = File.join(SPEC_TEMPDIR, "config.rb")
|
12
|
+
File.write(config_path, <<-CONFIG)
|
13
|
+
before_fork { File.write(ENV["LISTENER_PIDFILE"], $$.to_s) }
|
14
|
+
CONFIG
|
15
|
+
|
16
|
+
logfile = File.join(SPEC_TEMPDIR, "resqued.log")
|
17
|
+
File.write(logfile, "") # truncate it
|
18
|
+
|
19
|
+
env = {
|
20
|
+
"LISTENER_PIDFILE" => listener_pidfile,
|
21
|
+
"EXTRA_CHILD_PIDFILE" => extra_child_pidfile,
|
22
|
+
}
|
23
|
+
|
24
|
+
pid = spawn(env, shim_path, resqued_path, "--logfile", logfile, config_path)
|
25
|
+
sleep 1.0
|
26
|
+
pid
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:extra_child_pidfile) { File.join(SPEC_TEMPDIR, "extra-child.pid") }
|
30
|
+
def extra_child_pid
|
31
|
+
File.read(extra_child_pidfile).to_i
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:listener_pidfile) { File.join(File.join(SPEC_TEMPDIR, "listener.pid")) }
|
35
|
+
def listener_pid
|
36
|
+
File.read(listener_pidfile).to_i
|
37
|
+
end
|
38
|
+
|
39
|
+
before do
|
40
|
+
File.unlink(extra_child_pidfile) rescue nil
|
41
|
+
File.unlink(listener_pidfile) rescue nil
|
42
|
+
@resqued_pid = start_resqued_with_extra_child
|
43
|
+
end
|
44
|
+
|
45
|
+
after do
|
46
|
+
kill_safely(:TERM) { @resqued_pid }
|
47
|
+
kill_safely(:KILL) { extra_child_pid }
|
48
|
+
sleep 0.1
|
49
|
+
kill_safely(:KILL) { @resqued_pid }
|
50
|
+
end
|
51
|
+
|
52
|
+
it "doesn't exit when listener dies unexpectedly" do
|
53
|
+
# Kill off the listener process.
|
54
|
+
first_listener_pid = listener_pid
|
55
|
+
Process.kill :QUIT, first_listener_pid
|
56
|
+
# Let Resqued::Backoff decide it's OK to start the listener again.
|
57
|
+
sleep 2.5
|
58
|
+
# Resqued should start a new listener to replace the dead one.
|
59
|
+
expect(listener_pid).not_to eq(first_listener_pid)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "exits when listeners have all exited during shutdown" do
|
63
|
+
# Do a normal shutdown.
|
64
|
+
Process.kill :QUIT, @resqued_pid
|
65
|
+
# Expect the resqued process to exit.
|
66
|
+
expect(Timeout.timeout(5.0) { Process.waitpid(@resqued_pid) }).to eq(@resqued_pid)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "doesn't crash when extra child exits" do
|
70
|
+
# Kill off the extra child process. Resqued should wait on it, but not exit.
|
71
|
+
Process.kill :KILL, extra_child_pid
|
72
|
+
sleep 1.0
|
73
|
+
# The resqued process should not have exited.
|
74
|
+
expect(Process.waitpid(@resqued_pid, Process::WNOHANG)).to be_nil
|
75
|
+
expect(Process.kill(0, @resqued_pid)).to eq(1)
|
76
|
+
end
|
77
|
+
|
78
|
+
def kill_safely(signal)
|
79
|
+
return unless pid = yield
|
80
|
+
|
81
|
+
Process.kill(signal, pid)
|
82
|
+
rescue Errno::ESRCH, Errno::ENOENT
|
83
|
+
# Process isn't there anymore, or pidfile isn't there. :+1:
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Resqued can restart" do
|
4
|
+
include ResquedPath
|
5
|
+
|
6
|
+
it "expect to be able to restart" do
|
7
|
+
start_resqued
|
8
|
+
expect_running listener: "listener #1"
|
9
|
+
restart_resqued
|
10
|
+
expect_running listener: "listener #2"
|
11
|
+
stop_resqued
|
12
|
+
expect_not_running
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
begin
|
17
|
+
Process.kill(:QUIT, @pid) if @pid
|
18
|
+
rescue Errno::ESRCH
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def expect_running(listener:)
|
23
|
+
processes = list_processes
|
24
|
+
expect(processes).to include(is_resqued_master)
|
25
|
+
listeners = processes.select { |p| p[:ppid] == @pid }.map { |p| p[:args] }
|
26
|
+
expect(listeners).to all(match(/#{listener}/)).and(satisfy { |l| l.size == 1 })
|
27
|
+
end
|
28
|
+
|
29
|
+
def expect_not_running
|
30
|
+
processes = list_processes
|
31
|
+
expect(processes).not_to include(is_resqued_master)
|
32
|
+
end
|
33
|
+
|
34
|
+
def start_resqued
|
35
|
+
# Don't configure any workers. That way, we don't need to have redis running.
|
36
|
+
config_path = File.join(SPEC_TEMPDIR, "config.rb")
|
37
|
+
File.write(config_path, "")
|
38
|
+
|
39
|
+
logfile = File.join(SPEC_TEMPDIR, "resqued.log")
|
40
|
+
File.write(logfile, "") # truncate it
|
41
|
+
|
42
|
+
@pid = spawn resqued_path, "--logfile", logfile, config_path
|
43
|
+
sleep 1.0
|
44
|
+
end
|
45
|
+
|
46
|
+
def restart_resqued
|
47
|
+
Process.kill(:HUP, @pid)
|
48
|
+
sleep 1.0
|
49
|
+
end
|
50
|
+
|
51
|
+
def stop_resqued
|
52
|
+
Process.kill(:TERM, @pid)
|
53
|
+
sleep 1.0
|
54
|
+
end
|
55
|
+
|
56
|
+
def list_processes
|
57
|
+
`ps axo pid,ppid,args`.lines.map { |line| pid, ppid, args = line.strip.split(/\s+/, 3); { pid: pid.to_i, ppid: ppid.to_i, args: args } }
|
58
|
+
end
|
59
|
+
|
60
|
+
def is_resqued_master
|
61
|
+
satisfy { |p| p[:pid] == @pid && p[:args] =~ /resqued-/ }
|
62
|
+
end
|
63
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
module ResquedPath
|
2
|
+
def resqued_path
|
3
|
+
return @resqued_path if @resqued_path
|
4
|
+
|
5
|
+
@resqued_path = File.expand_path("../../gemfiles/bin/resqued", File.dirname(__FILE__))
|
6
|
+
unless File.executable?(@resqued_path)
|
7
|
+
@resqued_path = File.expand_path("../../bin/resqued", File.dirname(__FILE__))
|
8
|
+
end
|
9
|
+
@resqued_path
|
10
|
+
end
|
11
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resqued
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Burke
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kgio
|
@@ -137,6 +137,8 @@ files:
|
|
137
137
|
- spec/fixtures/test_case_clean.rb
|
138
138
|
- spec/fixtures/test_case_environment.rb
|
139
139
|
- spec/fixtures/test_case_no_workers.rb
|
140
|
+
- spec/integration/master_inherits_child_spec.rb
|
141
|
+
- spec/integration/restart_spec.rb
|
140
142
|
- spec/resqued/backoff_spec.rb
|
141
143
|
- spec/resqued/config/fork_event_spec.rb
|
142
144
|
- spec/resqued/config/worker_spec.rb
|
@@ -146,7 +148,8 @@ files:
|
|
146
148
|
- spec/resqued/test_case_spec.rb
|
147
149
|
- spec/spec_helper.rb
|
148
150
|
- spec/support/custom_matchers.rb
|
149
|
-
- spec/
|
151
|
+
- spec/support/extra-child-shim
|
152
|
+
- spec/support/resqued_path.rb
|
150
153
|
homepage: https://github.com/spraints/resqued
|
151
154
|
licenses:
|
152
155
|
- MIT
|
@@ -172,8 +175,11 @@ specification_version: 4
|
|
172
175
|
summary: Daemon of resque workers
|
173
176
|
test_files:
|
174
177
|
- spec/spec_helper.rb
|
175
|
-
- spec/
|
178
|
+
- spec/integration/restart_spec.rb
|
179
|
+
- spec/integration/master_inherits_child_spec.rb
|
176
180
|
- spec/support/custom_matchers.rb
|
181
|
+
- spec/support/resqued_path.rb
|
182
|
+
- spec/support/extra-child-shim
|
177
183
|
- spec/fixtures/test_case_clean.rb
|
178
184
|
- spec/fixtures/test_case_before_fork_raises.rb
|
179
185
|
- spec/fixtures/test_case_environment.rb
|
data/spec/test_restart.sh
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
#!/bin/bash
|
2
|
-
|
3
|
-
set -e
|
4
|
-
set -o nounset
|
5
|
-
|
6
|
-
WORKDIR="$(mktemp)"
|
7
|
-
PIDFILE="${WORKDIR}/resqued.pid"
|
8
|
-
CONFIG="${WORKDIR}/config.rb"
|
9
|
-
|
10
|
-
# mktemp makes a file, but we want a dir.
|
11
|
-
rm -f "$WORKDIR"
|
12
|
-
mkdir "$WORKDIR"
|
13
|
-
|
14
|
-
set -x
|
15
|
-
cd "$(dirname "$0")/.."
|
16
|
-
|
17
|
-
main() {
|
18
|
-
trap cleanup EXIT
|
19
|
-
|
20
|
-
configure_resqued
|
21
|
-
start_resqued
|
22
|
-
restart_resqued
|
23
|
-
stop_resqued
|
24
|
-
}
|
25
|
-
|
26
|
-
configure_resqued() {
|
27
|
-
# Don't configure any workers. That way, we don't need to have redis running.
|
28
|
-
touch "${CONFIG}"
|
29
|
-
}
|
30
|
-
|
31
|
-
start_resqued() {
|
32
|
-
bin_resqued=bin/resqued
|
33
|
-
if [ -x gemfiles/bin/resqued ]; then
|
34
|
-
bin_resqued=gemfiles/bin/resqued
|
35
|
-
fi
|
36
|
-
$bin_resqued --pidfile "${PIDFILE}" "${CONFIG}" &
|
37
|
-
sleep 1
|
38
|
-
echo expect to find the master process and the first listener
|
39
|
-
running # set -e will make the test fail if it's not running
|
40
|
-
ps axo pid,args -H | grep [r]esqued-
|
41
|
-
ps axo pid,args | grep [r]esqued- | grep -q 'listener #1.*running'
|
42
|
-
}
|
43
|
-
|
44
|
-
restart_resqued() {
|
45
|
-
local pid="$(cat "${PIDFILE}")"
|
46
|
-
kill -HUP "$pid"
|
47
|
-
sleep 1
|
48
|
-
echo expect to find the master process and the second listener
|
49
|
-
running
|
50
|
-
ps axo pid,args -H | grep [r]esqued-
|
51
|
-
ps axo pid,args | grep [r]esqued- | grep -qv 'listener #1'
|
52
|
-
ps axo pid,args | grep [r]esqued- | grep -q 'listener #2.*running'
|
53
|
-
}
|
54
|
-
|
55
|
-
stop_resqued() {
|
56
|
-
local pid="$(cat "${PIDFILE}")"
|
57
|
-
kill -TERM "$pid"
|
58
|
-
sleep 1
|
59
|
-
echo expect everything to be stopped
|
60
|
-
if running >&/dev/null; then
|
61
|
-
echo "expected resqued to be stopped"
|
62
|
-
false
|
63
|
-
fi
|
64
|
-
ps axo pid,args -H | grep [r]esqued- || true
|
65
|
-
test -z "$(ps axo pid,args | grep [r]esqued-)"
|
66
|
-
}
|
67
|
-
|
68
|
-
running() {
|
69
|
-
set -e
|
70
|
-
test -f "${PIDFILE}"
|
71
|
-
local pid="$(cat "${PIDFILE}")"
|
72
|
-
kill -0 "$pid"
|
73
|
-
ps o pid,args "$pid"
|
74
|
-
}
|
75
|
-
|
76
|
-
cleanup() {
|
77
|
-
while running >&/dev/null; do
|
78
|
-
kill -TERM "$(cat "${PIDFILE}")"
|
79
|
-
sleep 2
|
80
|
-
done
|
81
|
-
rm -rfv "${WORKDIR}" || rm -rf "${WORKDIR}"
|
82
|
-
}
|
83
|
-
|
84
|
-
main
|