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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 767297afcad9765330342e4dc397b27cdae3ca7c40e6d51c26b389d2708534a2
4
- data.tar.gz: dacfd4dcfc28b2f7d632d5dbfed1654fd226b30756f0e576efeee4560683c93e
3
+ metadata.gz: 7104c2e7f23dc24ebaf0fb864c8b53ae33ee02315c3a2baa91f60fea39eace6e
4
+ data.tar.gz: 3684ecfbc8f0285c9e4c9b6914f0940d74491cebf378651a679cfca7c4335183
5
5
  SHA512:
6
- metadata.gz: 272ea62737a31ca4c3a32d4fbc8e263a2c6642f03d962febb68a6fc61dc06139486ebff33decb224c4c0abce2e0f4ccd2f2df820534babacce8e7d9a78bbee68
7
- data.tar.gz: aa952102dc7c5e41c859c792bc4b1b5ce362d7f5d2edcc01b52f3c7dbe51d09f1752dcd40708b7d16fd1970fed4c9bb5a5229903ba2dda2be3fa9dc11b436205
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
- [![travis status](https://travis-ci.org/spraints/resqued.png)](https://travis-ci.org/spraints/resqued)
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 restarts when its master process receives `SIGHUP`. It restarts by re-execing the command that you initially ran. There are two main recommendations for running in production.
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
- Rolling all of the above advice together, here's a sample that you could use in an upstart script for resqued:
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 /etc/init/resqued.conf
78
-
79
- kill signal QUIT
81
+ # fragment of resqued.service
80
82
 
81
- env BUNDLE_GEMFILE=/opt/app/current/Gemfile
82
- env PWD=/opt/app/current
83
- chdir /opt/app/current
83
+ [Service]
84
+ Type=simple
84
85
 
85
- exec bin/resqued -c config/resqued.rb -p /opt/app/shared/tmp/pids/resqued.pid
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 = { exec_on_hup: true }
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::ExecOnHUP.restore_state(state, options[:master_state])
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!
@@ -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
@@ -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 initial values.
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 should be forwarded to a new master.
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 ExecOnHUP
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)
@@ -1,3 +1,3 @@
1
1
  module Resqued
2
- VERSION = "0.12.4".freeze
2
+ VERSION = "0.13.0".freeze
3
3
  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.12.4
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-05 00:00:00.000000000 Z
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