resqued 0.12.4 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +10 -0
- data/README.md +13 -10
- data/docs/signals.md +2 -0
- data/exe/resqued +2 -6
- data/lib/resqued/master.rb +5 -6
- data/lib/resqued/master_state.rb +31 -2
- data/lib/resqued/{exec_on_hup.rb → replace_master.rb} +1 -1
- data/lib/resqued/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7104c2e7f23dc24ebaf0fb864c8b53ae33ee02315c3a2baa91f60fea39eace6e
|
4
|
+
data.tar.gz: 3684ecfbc8f0285c9e4c9b6914f0940d74491cebf378651a679cfca7c4335183
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5e4cf0be88ae6fc02951ab7a7262d67cc9dac404696265a7cf785a2646ead92faa6eed0c686fc56b0844fa958753a18161d5d8d1d23474fa805ca52e79fd0f3
|
7
|
+
data.tar.gz: 51cf8397eec968b97b525d83506e3fbb8c84d0b11c989089c926b6242da0bb54dd0ad02ada99cfc370463d1aaaa94fb6257adcd6904e298a87cf352e9c6841c4
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,15 @@
|
|
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.13.0
|
4
|
+
-------
|
5
|
+
* Re-exec on SIGUSR1 instead of SIGHUP. There should be no compatibility
|
6
|
+
problem between 0.12 and 0.13, but the behavior will be different. If you
|
7
|
+
start 0.12 and then upgrade to 0.13, resqued will re-exec on HUP until it
|
8
|
+
hits 0.13. If you downgrade to 0.12, resqued's master will stay at 0.13 even
|
9
|
+
though the listener changes to 0.12; `kill -USR1 $pid` to get the 0.13 master
|
10
|
+
to roll back to 0.12, too. Note: take care not to `kill -USR1` a 0.12
|
11
|
+
resqued, as that will cause it to shut down. (#71)
|
12
|
+
|
3
13
|
v0.12.4
|
4
14
|
-------
|
5
15
|
* Add support for redis client gem version 5. (#70)
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Resqued is a multi-process daemon that controls and monitors a pool of resque workers. It works well with slow jobs and continuous delivery.
|
4
4
|
|
5
|
-
|
5
|
+
![CI status](https://github.com/spraints/resqued/actions/workflows/ruby.yml/badge.svg)
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -57,7 +57,11 @@ This time, you'd end up with something similar to this:
|
|
57
57
|
|
58
58
|
## Launching in production.
|
59
59
|
|
60
|
-
Resqued
|
60
|
+
Resqued consists of three types of processes: master, listener, and worker. The master process only loads code from the resqued gem, and it tries to converge on running exactly one listener. The listener process loads your app's code (via the `before_fork` hook) and launches the workers you've configured. Each worker is a single process.
|
61
|
+
|
62
|
+
Resqued restarts on SIGHUP by starting a new listener, and then replacing workers from the old pool with workers in the new pool. Note that this means that if you change the version of Resqued in your bundle, the master and listener processes will be using different versions. This is completely safe (except as noted in CHANGES.md). But, to help with transitions between versions, you can use `kill -USR1` to tell the master process to re-exec itself, which will get the master and listener processes in sync again.
|
63
|
+
|
64
|
+
There are two main recommendations for running in production:
|
61
65
|
|
62
66
|
* If you use bundler to install resqued, tell it to generate a binstub for resqued. Invoke this binstub (e.g. `bin/resqued`) when you start resqued.
|
63
67
|
|
@@ -71,18 +75,17 @@ If your application is running from a symlinked dir (for example, [capistrano's
|
|
71
75
|
|
72
76
|
* If you're invoking resqued from something that resolves symlinks in `pwd`, you'll also want to explicitly set the `PWD` environment variable.
|
73
77
|
|
74
|
-
|
78
|
+
Putting all of the above advice together, here's a sample that you could use as a systemd unit:
|
75
79
|
|
76
80
|
```
|
77
|
-
# fragment of
|
78
|
-
|
79
|
-
kill signal QUIT
|
81
|
+
# fragment of resqued.service
|
80
82
|
|
81
|
-
|
82
|
-
|
83
|
-
chdir /opt/app/current
|
83
|
+
[Service]
|
84
|
+
Type=simple
|
84
85
|
|
85
|
-
|
86
|
+
WorkingDirectory=/opt/app/current
|
87
|
+
ExecStart=bin/resqued config/resqued.rb
|
88
|
+
ExecReload=/bin/kill -HUP $MAINPID
|
86
89
|
```
|
87
90
|
|
88
91
|
## Compatibility with Resque
|
data/docs/signals.md
CHANGED
@@ -8,6 +8,7 @@ Here is a summary of how signals get passed between resqued's processes:
|
|
8
8
|
master listener worker
|
9
9
|
------ -------- ------
|
10
10
|
restart HUP -> QUIT -> QUIT
|
11
|
+
reexec master USR1 -> QUIT -> QUIT
|
11
12
|
exit now INT -> INT -> INT
|
12
13
|
exit now TERM -> TERM -> TERM
|
13
14
|
exit when ready QUIT -> QUIT -> QUIT
|
@@ -23,6 +24,7 @@ Read on for more information about what the signals mean.
|
|
23
24
|
The Master process handles several signals.
|
24
25
|
|
25
26
|
* `HUP`: Start a new listener. After it boots, kill the previous listener with `SIGQUIT`.
|
27
|
+
* `USR1`: Re-exec the master process, preserving the current state. Also exec a new listener.
|
26
28
|
* `USR2`: Pause processing. Kills the current listener, and does not start a replacement.
|
27
29
|
* `CONT`: Resume processing. If there is no listener, start one. If there is a listener, send it `SIGCONT`.
|
28
30
|
* `QUIT`, `INT`, or `TERM`: Kill the listener with the same signal and wait for it to exit. If `--fast-exit` was specified, the master exits immediately without waiting for the listener to exit.
|
data/exe/resqued
CHANGED
@@ -13,7 +13,7 @@ end
|
|
13
13
|
|
14
14
|
require "optparse"
|
15
15
|
|
16
|
-
options = {
|
16
|
+
options = {}
|
17
17
|
daemonize = false
|
18
18
|
test = false
|
19
19
|
|
@@ -52,10 +52,6 @@ opts = OptionParser.new do |opts| # rubocop: disable Lint/ShadowingOuterLocalVar
|
|
52
52
|
daemonize = true
|
53
53
|
end
|
54
54
|
|
55
|
-
opts.on "--no-exec-on-hup", "Do not re-exec the master process on SIGHUP" do
|
56
|
-
options[:exec_on_hup] = false
|
57
|
-
end
|
58
|
-
|
59
55
|
opts.on "--replace FILE", "(internal)" do |v|
|
60
56
|
options[:master_state] = v
|
61
57
|
end
|
@@ -84,7 +80,7 @@ else
|
|
84
80
|
state = Resqued::MasterState.new
|
85
81
|
if options[:master_state]
|
86
82
|
Resqued::Logging.logger.info "Resuming master from #{options[:master_state]}"
|
87
|
-
Resqued::
|
83
|
+
Resqued::ReplaceMaster.restore_state(state, options[:master_state])
|
88
84
|
else
|
89
85
|
require_config_paths! options, opts
|
90
86
|
Resqued.capture_start_ctx!
|
data/lib/resqued/master.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require "resqued/backoff"
|
2
|
-
require "resqued/exec_on_hup"
|
3
2
|
require "resqued/listener_pool"
|
4
3
|
require "resqued/logging"
|
5
4
|
require "resqued/master_state"
|
6
5
|
require "resqued/pidfile"
|
7
6
|
require "resqued/procline_version"
|
7
|
+
require "resqued/replace_master"
|
8
8
|
require "resqued/sleepy"
|
9
9
|
|
10
10
|
module Resqued
|
@@ -55,13 +55,12 @@ module Resqued
|
|
55
55
|
when :INFO
|
56
56
|
dump_object_counts
|
57
57
|
when :HUP
|
58
|
-
if @state.exec_on_hup
|
59
|
-
log "Execing a new master"
|
60
|
-
ExecOnHUP.exec!(@state)
|
61
|
-
end
|
62
58
|
reopen_logs
|
63
59
|
log "Restarting listener with new configuration and application."
|
64
60
|
prepare_new_listener
|
61
|
+
when :USR1
|
62
|
+
log "Execing a new master"
|
63
|
+
ReplaceMaster.exec!(@state)
|
65
64
|
when :USR2
|
66
65
|
log "Pause job processing"
|
67
66
|
@state.paused = true
|
@@ -215,7 +214,7 @@ module Resqued
|
|
215
214
|
end
|
216
215
|
end
|
217
216
|
|
218
|
-
SIGNALS = [:HUP, :INT, :USR2, :CONT, :TERM, :QUIT].freeze
|
217
|
+
SIGNALS = [:HUP, :INT, :USR1, :USR2, :CONT, :TERM, :QUIT].freeze
|
219
218
|
OPTIONAL_SIGNALS = [:INFO].freeze
|
220
219
|
OTHER_SIGNALS = [:CHLD, "EXIT"].freeze
|
221
220
|
TRAPS = SIGNALS + OPTIONAL_SIGNALS + OTHER_SIGNALS
|
data/lib/resqued/master_state.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
module Resqued
|
2
|
+
# Tracks state from the master process. On re-exec, this object will
|
3
|
+
# be serialized and passed to the new master.
|
2
4
|
class MasterState
|
3
5
|
def initialize
|
4
6
|
@listeners_created = 0
|
5
7
|
@listener_states = {}
|
6
8
|
end
|
7
9
|
|
8
|
-
# Public: When starting fresh, from command-line options, assign the
|
10
|
+
# Public: When starting fresh, from command-line options, assign the
|
11
|
+
# initial values.
|
9
12
|
def init(options)
|
10
13
|
@config_paths = options.fetch(:config_paths)
|
11
14
|
@exec_on_hup = options.fetch(:exec_on_hup, false)
|
@@ -55,19 +58,45 @@ module Resqued
|
|
55
58
|
}
|
56
59
|
end
|
57
60
|
|
58
|
-
# Public: Return an array of open sockets or other file handles that
|
61
|
+
# Public: Return an array of open sockets or other file handles that
|
62
|
+
# should be forwarded to a new master.
|
59
63
|
def sockets
|
60
64
|
@listener_states.values.map { |l| l.master_socket }.compact
|
61
65
|
end
|
62
66
|
|
67
|
+
# Paths of app's resqued configuration files. The paths are passed
|
68
|
+
# to the listener, and the listener reads the config so that it
|
69
|
+
# knows which workers to create.
|
63
70
|
attr_reader :config_paths
|
71
|
+
|
72
|
+
# The PID of the newest listener. This is the one listener that
|
73
|
+
# should continue running.
|
64
74
|
attr_accessor :current_listener_pid
|
75
|
+
|
76
|
+
# (Deprecated.) If true, on SIGHUP re-exec the master process before
|
77
|
+
# starting a new listener.
|
65
78
|
attr_reader :exec_on_hup
|
79
|
+
|
80
|
+
# If true, on SIGTERM/SIGQUIT/SIGINT, don't wait for listeners to
|
81
|
+
# exit before the master exits.
|
66
82
|
attr_reader :fast_exit
|
83
|
+
|
84
|
+
# The PID of the newest listener that booted successfully. This
|
85
|
+
# listener won't be stopped until a newer listener boots
|
86
|
+
# successfully.
|
67
87
|
attr_accessor :last_good_listener_pid
|
88
|
+
|
89
|
+
# The number of listeners that have been created by this master.
|
68
90
|
attr_accessor :listeners_created
|
91
|
+
|
92
|
+
# A hash of pid => ListenerState for all running listeners.
|
69
93
|
attr_reader :listener_states
|
94
|
+
|
95
|
+
# Set to true when this master is paused and should not be running
|
96
|
+
# any listeners.
|
70
97
|
attr_accessor :paused
|
98
|
+
|
99
|
+
# If set, the master's PID will be written to this file.
|
71
100
|
attr_reader :pidfile
|
72
101
|
end
|
73
102
|
end
|
@@ -2,7 +2,7 @@ require "tempfile"
|
|
2
2
|
require "yaml"
|
3
3
|
|
4
4
|
module Resqued
|
5
|
-
class
|
5
|
+
class ReplaceMaster
|
6
6
|
# Public: Replace the current master process with a new one, while preserving state.
|
7
7
|
def self.exec!(state)
|
8
8
|
exec Resqued::START_CTX["$0"], "--replace", store_state(state), exec_opts(state)
|
data/lib/resqued/version.rb
CHANGED
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.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Burke
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01
|
11
|
+
date: 2023-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kgio
|
@@ -118,7 +118,6 @@ files:
|
|
118
118
|
- lib/resqued/config/dsl.rb
|
119
119
|
- lib/resqued/config/worker.rb
|
120
120
|
- lib/resqued/daemon.rb
|
121
|
-
- lib/resqued/exec_on_hup.rb
|
122
121
|
- lib/resqued/listener.rb
|
123
122
|
- lib/resqued/listener_pool.rb
|
124
123
|
- lib/resqued/listener_proxy.rb
|
@@ -129,6 +128,7 @@ files:
|
|
129
128
|
- lib/resqued/pidfile.rb
|
130
129
|
- lib/resqued/procline_version.rb
|
131
130
|
- lib/resqued/quit-and-wait.rb
|
131
|
+
- lib/resqued/replace_master.rb
|
132
132
|
- lib/resqued/runtime_info.rb
|
133
133
|
- lib/resqued/sleepy.rb
|
134
134
|
- lib/resqued/test_case.rb
|