resqued 0.10.1 → 0.10.2
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.
- 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
|