resqued 0.9.0 → 0.10.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 +6 -0
- data/exe/resqued +41 -22
- data/lib/resqued.rb +5 -5
- data/lib/resqued/config.rb +7 -7
- data/lib/resqued/config/after_fork.rb +1 -1
- data/lib/resqued/config/base.rb +1 -1
- data/lib/resqued/config/before_fork.rb +1 -1
- data/lib/resqued/config/worker.rb +12 -12
- data/lib/resqued/daemon.rb +1 -0
- data/lib/resqued/exec_on_hup.rb +43 -0
- data/lib/resqued/listener.rb +48 -48
- data/lib/resqued/listener_pool.rb +92 -0
- data/lib/resqued/listener_proxy.rb +37 -31
- data/lib/resqued/listener_state.rb +8 -0
- data/lib/resqued/logging.rb +15 -8
- data/lib/resqued/master.rb +91 -97
- data/lib/resqued/master_state.rb +73 -0
- data/lib/resqued/procline_version.rb +2 -2
- data/lib/resqued/sleepy.rb +6 -4
- data/lib/resqued/test_case.rb +3 -3
- data/lib/resqued/version.rb +1 -1
- data/lib/resqued/worker.rb +16 -13
- data/spec/fixtures/test_case_after_fork_raises.rb +5 -2
- data/spec/fixtures/test_case_before_fork_raises.rb +4 -1
- data/spec/fixtures/test_case_environment.rb +3 -1
- data/spec/resqued/backoff_spec.rb +19 -19
- data/spec/resqued/config/fork_event_spec.rb +8 -8
- data/spec/resqued/config/worker_spec.rb +52 -50
- data/spec/resqued/config_spec.rb +6 -6
- data/spec/resqued/sleepy_spec.rb +10 -11
- data/spec/resqued/test_case_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -1
- data/spec/support/custom_matchers.rb +1 -1
- data/spec/test_restart.sh +84 -0
- metadata +31 -13
- data/exe/resqued-listener +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d56c813a2d3adf7d10fe76dafefff24c263f9766
|
4
|
+
data.tar.gz: e3c9cd5fc92aca0b70d4d8ed31de6f15c418c94c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a28be514424a281b554224c78ba0d4fa6ff328f1d9fff622c76653c09ceefc6bc6c70cdb389d41dbd566fa202741d073ad6817103d2231237cbfdd726dd32473
|
7
|
+
data.tar.gz: 14375d125a0c9e89ecc1918fa6d46f062206ddc0ac08a3ac8f504e7aeab563f90ea3d62cb54b955b1408f3308692b9cc98479c19d2d420b0136d73c10182687d
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,11 @@
|
|
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.0
|
4
|
+
-------
|
5
|
+
* Master process restarts itself (#51), so that it doesn't continue running stale code indefinitely. This will help with the rollout process when changes like #50 are introduced, so that the master process will catch up. The risk of this is that the master process might not be able to be restarted, which would lead to it crashing. The mostly likely way for that to happen is if you try to roll back your version of resqued to 0.9.0 or earlier. If you need to do that, ensure that your process monitor (systemd, god, etc.) is able to restart the master process. You can disable the new behavior by passing `--no-exec-on-hup`.
|
6
|
+
* Added rubocop. (#52)
|
7
|
+
* Changed supported (read: tested in CI) ruby versions from [2.0 .. 2.3] to [2.3 .. 2.6].
|
8
|
+
|
3
9
|
v0.9.0
|
4
10
|
------
|
5
11
|
* Avoid Errno::E2BIG on SIGHUP when there are lots of workers and lots of queues per worker. (#50) This changes the format of an env var that master passes to listener. Old and new versions won't crash, but they won't be able to communicate about currenly running workers.
|
data/exe/resqued
CHANGED
@@ -1,74 +1,93 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
if ARGV[0] ==
|
4
|
-
require
|
3
|
+
if ARGV[0] == "listener"
|
4
|
+
require "resqued/listener"
|
5
5
|
Resqued::Listener.exec!
|
6
6
|
exit 0
|
7
7
|
end
|
8
8
|
|
9
|
-
require
|
9
|
+
require "optparse"
|
10
10
|
|
11
|
-
options = {}
|
11
|
+
options = { exec_on_hup: true }
|
12
12
|
daemonize = false
|
13
13
|
test = false
|
14
14
|
|
15
|
-
opts = OptionParser.new do |opts|
|
15
|
+
opts = OptionParser.new do |opts| # rubocop: disable Lint/ShadowingOuterLocalVariable
|
16
16
|
opts.banner = "Usage: resqued [options] resqued-config-files..."
|
17
17
|
|
18
|
-
opts.on
|
18
|
+
opts.on "-h", "--help", "Show this message" do
|
19
19
|
puts opts
|
20
20
|
exit
|
21
21
|
end
|
22
22
|
|
23
|
-
opts.on
|
24
|
-
require
|
23
|
+
opts.on "-v", "--version", "Show the version" do
|
24
|
+
require "resqued/version"
|
25
25
|
puts Resqued::VERSION
|
26
26
|
exit
|
27
27
|
end
|
28
28
|
|
29
|
-
opts.on
|
29
|
+
opts.on "--test", "Report which worker would start" do
|
30
30
|
test = true
|
31
31
|
end
|
32
32
|
|
33
|
-
opts.on
|
33
|
+
opts.on "--fast-exit", "Exit quickly on SIGQUIT, SIGTERM" do
|
34
34
|
options[:fast_exit] = true
|
35
35
|
end
|
36
36
|
|
37
|
-
opts.on
|
37
|
+
opts.on "-p", "--pidfile PIDFILE", "Store the pid of the master process in PIDFILE" do |v|
|
38
38
|
options[:master_pidfile] = v
|
39
39
|
end
|
40
40
|
|
41
|
-
opts.on
|
42
|
-
require
|
41
|
+
opts.on "-l", "--logfile LOGFILE", "Write output to LOGFILE instead of stdout" do |v|
|
42
|
+
require "resqued/logging"
|
43
43
|
Resqued::Logging.log_file = v
|
44
44
|
end
|
45
45
|
|
46
|
-
opts.on
|
46
|
+
opts.on "-D", "--daemonize", "Run daemonized in the background" do
|
47
47
|
daemonize = true
|
48
48
|
end
|
49
|
+
|
50
|
+
opts.on "--no-exec-on-hup", "Do not re-exec the master process on SIGHUP" do
|
51
|
+
options[:exec_on_hup] = false
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on "--replace FILE", "(internal)" do |v|
|
55
|
+
options[:master_state] = v
|
56
|
+
end
|
49
57
|
end
|
50
58
|
|
51
59
|
opts.parse!
|
52
60
|
options[:config_paths] = ARGV
|
53
61
|
|
54
|
-
|
55
|
-
|
56
|
-
|
62
|
+
def require_config_paths!(options, opts)
|
63
|
+
if options[:config_paths].empty?
|
64
|
+
puts opts
|
65
|
+
exit 1
|
66
|
+
end
|
57
67
|
end
|
58
68
|
|
59
69
|
if test
|
60
|
-
|
70
|
+
require_config_paths! options, opts
|
71
|
+
require "resqued/config"
|
61
72
|
workers = Resqued::Config.new(options[:config_paths]).build_workers
|
62
73
|
puts "Workers defined in #{options[:config_paths].join(' ')}"
|
63
74
|
workers.each_with_index do |worker, index|
|
64
75
|
puts "#{index + 1}: #{worker.queues.join(',')}"
|
65
76
|
end
|
66
77
|
else
|
67
|
-
require
|
68
|
-
Resqued.
|
69
|
-
|
78
|
+
require "resqued"
|
79
|
+
state = Resqued::MasterState.new
|
80
|
+
if options[:master_state]
|
81
|
+
Resqued::Logging.logger.info "Resuming master from #{options[:master_state]}"
|
82
|
+
Resqued::ExecOnHUP.restore_state(state, options[:master_state])
|
83
|
+
else
|
84
|
+
require_config_paths! options, opts
|
85
|
+
Resqued.capture_start_ctx!
|
86
|
+
state.init(options)
|
87
|
+
end
|
88
|
+
resqued = Resqued::Master.new(state)
|
70
89
|
if daemonize
|
71
|
-
require
|
90
|
+
require "resqued/daemon"
|
72
91
|
resqued = Resqued::Daemon.new(resqued)
|
73
92
|
end
|
74
93
|
resqued.run
|
data/lib/resqued.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "resqued/master"
|
2
|
+
require "resqued/version"
|
3
3
|
|
4
4
|
module Resqued
|
5
|
-
START_CTX = {}
|
5
|
+
START_CTX = {} # rubocop: disable Style/MutableConstant
|
6
6
|
|
7
7
|
def self.capture_start_ctx!
|
8
|
-
START_CTX[
|
9
|
-
START_CTX[
|
8
|
+
START_CTX["$0"] = $0.dup
|
9
|
+
START_CTX["pwd"] =
|
10
10
|
begin
|
11
11
|
env_pwd = ENV["PWD"]
|
12
12
|
env_pwd_stat = File.stat env_pwd
|
data/lib/resqued/config.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "resqued/config/after_fork"
|
2
|
+
require "resqued/config/before_fork"
|
3
|
+
require "resqued/config/worker"
|
4
4
|
|
5
5
|
module Resqued
|
6
6
|
module Config
|
@@ -14,22 +14,22 @@ module Resqued
|
|
14
14
|
# Does the things that the config file says to do.
|
15
15
|
class Configuration
|
16
16
|
def initialize(config_paths)
|
17
|
-
@config_data = config_paths.map { |path| {:
|
17
|
+
@config_data = config_paths.map { |path| { content: File.read(path), path: path } }
|
18
18
|
end
|
19
19
|
|
20
20
|
# Public: Performs the `before_fork` action from the config.
|
21
21
|
def before_fork(resqued)
|
22
|
-
Resqued::Config::BeforeFork.new(:
|
22
|
+
Resqued::Config::BeforeFork.new(resqued: resqued).apply_all(@config_data)
|
23
23
|
end
|
24
24
|
|
25
25
|
# Public: Performs the `after_fork` action from the config.
|
26
26
|
def after_fork(worker)
|
27
|
-
Resqued::Config::AfterFork.new(:
|
27
|
+
Resqued::Config::AfterFork.new(worker: worker).apply_all(@config_data)
|
28
28
|
end
|
29
29
|
|
30
30
|
# Public: Builds the workers specified in the config.
|
31
31
|
def build_workers
|
32
|
-
Resqued::Config::Worker.new(:
|
32
|
+
Resqued::Config::Worker.new(config: self).apply_all(@config_data)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
data/lib/resqued/config/base.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "resqued/config/base"
|
2
|
+
require "resqued/worker"
|
3
3
|
|
4
4
|
module Resqued
|
5
5
|
module Config
|
@@ -21,9 +21,9 @@ module Resqued
|
|
21
21
|
def worker(*queues)
|
22
22
|
options = queues.last.is_a?(Hash) ? queues.pop.dup : {}
|
23
23
|
queues = queues.flatten
|
24
|
-
queues = [
|
24
|
+
queues = ["*"] if queues.empty?
|
25
25
|
queues = queues.shuffle if options.delete(:shuffle_queues)
|
26
|
-
@workers << @worker_class.new(options.merge(@worker_options).merge(:
|
26
|
+
@workers << @worker_class.new(options.merge(@worker_options).merge(queues: queues))
|
27
27
|
end
|
28
28
|
|
29
29
|
# DSL: Set up a pool of workers. Define queues for the members of the pool with `queue`.
|
@@ -81,15 +81,16 @@ module Resqued
|
|
81
81
|
# on the concurrency values established and the total number of workers.
|
82
82
|
def build_pool_workers!
|
83
83
|
return unless @pool_size
|
84
|
+
|
84
85
|
queues = _fixed_concurrency_queues
|
85
86
|
1.upto(@pool_size) do |worker_num|
|
86
|
-
queue_names = queues
|
87
|
-
|
88
|
-
|
87
|
+
queue_names = queues
|
88
|
+
.select { |_name, concurrency| concurrency >= worker_num }
|
89
|
+
.map { |name, _concurrency| name }
|
89
90
|
if queue_names.any?
|
90
91
|
worker(queue_names, @pool_options)
|
91
92
|
else
|
92
|
-
worker(
|
93
|
+
worker("*", @pool_options)
|
93
94
|
end
|
94
95
|
end
|
95
96
|
end
|
@@ -106,12 +107,11 @@ module Resqued
|
|
106
107
|
# values (between 0.0 and 1.0). The value may also be nil, in which case the
|
107
108
|
# maximum worker_processes value is returned.
|
108
109
|
def _translate_concurrency_value(value)
|
109
|
-
|
110
|
-
when value.nil?
|
110
|
+
if value.nil?
|
111
111
|
@pool_size
|
112
|
-
|
112
|
+
elsif value.is_a?(1.class)
|
113
113
|
value < @pool_size ? value : @pool_size
|
114
|
-
|
114
|
+
elsif value.is_a?(Float) && value >= 0.0 && value <= 1.0
|
115
115
|
(@pool_size * value).to_i
|
116
116
|
else
|
117
117
|
raise TypeError, "Unknown concurrency value: #{value.inspect}"
|
data/lib/resqued/daemon.rb
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
module Resqued
|
5
|
+
class ExecOnHUP
|
6
|
+
# Public: Replace the current master process with a new one, while preserving state.
|
7
|
+
def self.exec!(state)
|
8
|
+
exec Resqued::START_CTX["$0"], "--replace", store_state(state), exec_opts(state)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Internal: Returns exec options for each open socket in 'state'.
|
12
|
+
def self.exec_opts(state)
|
13
|
+
exec_opts = {}
|
14
|
+
state.sockets.each do |sock|
|
15
|
+
exec_opts[sock.to_i] = sock
|
16
|
+
end
|
17
|
+
if pwd = Resqued::START_CTX["pwd"]
|
18
|
+
exec_opts[:chdir] = pwd
|
19
|
+
end
|
20
|
+
return exec_opts
|
21
|
+
end
|
22
|
+
|
23
|
+
# Internal: Write out current state to a file, so that a new master can pick up from where we left off.
|
24
|
+
def self.store_state(state)
|
25
|
+
data = { version: Resqued::VERSION }
|
26
|
+
data[:start_ctx] = Resqued::START_CTX
|
27
|
+
data[:state] = state.to_h
|
28
|
+
|
29
|
+
f = Tempfile.create "resqued-state"
|
30
|
+
f.write(YAML.dump(data))
|
31
|
+
f.close
|
32
|
+
return f.path
|
33
|
+
end
|
34
|
+
|
35
|
+
# Internal: Restore the master's state, and remove the state file.
|
36
|
+
def self.restore_state(state, path)
|
37
|
+
data = YAML.safe_load(File.read(path), [Symbol], [], true)
|
38
|
+
Resqued::START_CTX.replace(data[:start_ctx] || {})
|
39
|
+
state.restore(data[:state])
|
40
|
+
File.unlink(path) rescue nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/resqued/listener.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require "socket"
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
3
|
+
require "resqued/config"
|
4
|
+
require "resqued/logging"
|
5
|
+
require "resqued/procline_version"
|
6
|
+
require "resqued/runtime_info"
|
7
|
+
require "resqued/sleepy"
|
8
|
+
require "resqued/version"
|
9
|
+
require "resqued/worker"
|
10
10
|
|
11
11
|
module Resqued
|
12
12
|
# A listener process. Watches resque queues and forks workers.
|
@@ -30,67 +30,67 @@ module Resqued
|
|
30
30
|
# Runs in the master process.
|
31
31
|
def exec
|
32
32
|
socket_fd = @socket.to_i
|
33
|
-
ENV[
|
34
|
-
ENV[
|
35
|
-
ENV[
|
36
|
-
ENV[
|
37
|
-
ENV[
|
33
|
+
ENV["RESQUED_SOCKET"] = socket_fd.to_s
|
34
|
+
ENV["RESQUED_CONFIG_PATH"] = @config_paths.join(":")
|
35
|
+
ENV["RESQUED_STATE"] = @old_workers.map { |r| "#{r[:pid]}|#{r[:queue_key]}" }.join("||")
|
36
|
+
ENV["RESQUED_LISTENER_ID"] = @listener_id.to_s
|
37
|
+
ENV["RESQUED_MASTER_VERSION"] = Resqued::VERSION
|
38
38
|
log "exec: #{Resqued::START_CTX['$0']} listener"
|
39
|
-
exec_opts = {socket_fd => socket_fd} # Ruby 2.0 needs to be told to keep the file descriptor open during exec.
|
40
|
-
if start_pwd = Resqued::START_CTX[
|
39
|
+
exec_opts = { socket_fd => socket_fd } # Ruby 2.0 needs to be told to keep the file descriptor open during exec.
|
40
|
+
if start_pwd = Resqued::START_CTX["pwd"]
|
41
41
|
exec_opts[:chdir] = start_pwd
|
42
42
|
end
|
43
|
-
procline_buf =
|
44
|
-
Kernel.exec(Resqued::START_CTX[
|
43
|
+
procline_buf = " " * 256 # make room for setproctitle
|
44
|
+
Kernel.exec(Resqued::START_CTX["$0"], "listener", procline_buf, exec_opts)
|
45
45
|
end
|
46
46
|
|
47
47
|
# Public: Given args from #exec, start this listener.
|
48
48
|
def self.exec!
|
49
49
|
options = {}
|
50
|
-
if socket = ENV[
|
50
|
+
if socket = ENV["RESQUED_SOCKET"]
|
51
51
|
options[:socket] = Socket.for_fd(socket.to_i)
|
52
52
|
end
|
53
|
-
if path = ENV[
|
54
|
-
options[:config_paths] = path.split(
|
53
|
+
if path = ENV["RESQUED_CONFIG_PATH"]
|
54
|
+
options[:config_paths] = path.split(":")
|
55
55
|
end
|
56
|
-
if state = ENV[
|
57
|
-
options[:old_workers] = state.split(
|
56
|
+
if state = ENV["RESQUED_STATE"]
|
57
|
+
options[:old_workers] = state.split("||").map { |s| Hash[[:pid, :queue_key].zip(s.split("|"))] }
|
58
58
|
end
|
59
|
-
if listener_id = ENV[
|
59
|
+
if listener_id = ENV["RESQUED_LISTENER_ID"]
|
60
60
|
options[:listener_id] = listener_id
|
61
61
|
end
|
62
62
|
new(options).run
|
63
63
|
end
|
64
64
|
|
65
|
-
SIGNALS = [
|
66
|
-
ALL_SIGNALS = SIGNALS + [
|
65
|
+
SIGNALS = [:CONT, :QUIT, :INT, :TERM].freeze
|
66
|
+
ALL_SIGNALS = SIGNALS + [:CHLD]
|
67
67
|
|
68
|
-
SIGNAL_QUEUE = []
|
68
|
+
SIGNAL_QUEUE = [] # rubocop: disable Style/MutableConstant
|
69
69
|
|
70
70
|
# Public: Run the main loop.
|
71
71
|
def run
|
72
72
|
trap(:CHLD) { awake }
|
73
|
-
SIGNALS.each { |signal| trap(signal) { SIGNAL_QUEUE << signal
|
73
|
+
SIGNALS.each { |signal| trap(signal) { SIGNAL_QUEUE << signal; awake } }
|
74
74
|
@socket.close_on_exec = true
|
75
|
-
write_procline(
|
75
|
+
write_procline("starting")
|
76
76
|
|
77
77
|
config = Resqued::Config.new(@config_paths)
|
78
78
|
set_default_resque_logger
|
79
79
|
config.before_fork(info)
|
80
80
|
report_to_master("RUNNING")
|
81
81
|
|
82
|
-
write_procline(
|
82
|
+
write_procline("running")
|
83
83
|
init_workers(config)
|
84
84
|
exit_signal = run_workers_run
|
85
85
|
|
86
|
-
write_procline(
|
86
|
+
write_procline("shutdown")
|
87
87
|
burn_down_workers(exit_signal || :QUIT)
|
88
88
|
end
|
89
89
|
|
90
90
|
# Private.
|
91
91
|
def set_default_resque_logger
|
92
|
-
require
|
93
|
-
if Resque.respond_to?(
|
92
|
+
require "resque"
|
93
|
+
if Resque.respond_to?("logger=")
|
94
94
|
Resque.logger = Resqued::Logging.build_logger
|
95
95
|
end
|
96
96
|
end
|
@@ -101,7 +101,7 @@ module Resqued
|
|
101
101
|
reap_workers(Process::WNOHANG)
|
102
102
|
check_for_expired_workers
|
103
103
|
start_idle_workers
|
104
|
-
write_procline(
|
104
|
+
write_procline("running")
|
105
105
|
case signal = SIGNAL_QUEUE.shift
|
106
106
|
when nil
|
107
107
|
yawn
|
@@ -119,10 +119,11 @@ module Resqued
|
|
119
119
|
def burn_down_workers(signal)
|
120
120
|
loop do
|
121
121
|
check_for_expired_workers
|
122
|
-
write_procline(
|
122
|
+
write_procline("shutdown")
|
123
123
|
SIGNAL_QUEUE.clear
|
124
124
|
|
125
125
|
break if :no_child == reap_workers(Process::WNOHANG)
|
126
|
+
|
126
127
|
kill_all(signal)
|
127
128
|
|
128
129
|
sleep 1 # Don't kill any more often than every 1s.
|
@@ -134,7 +135,7 @@ module Resqued
|
|
134
135
|
|
135
136
|
# Private: send a signal to all the workers.
|
136
137
|
def kill_all(signal)
|
137
|
-
|
138
|
+
running = running_workers
|
138
139
|
log "kill -#{signal} #{running.map { |r| r.pid }.inspect}"
|
139
140
|
running.each { |worker| worker.kill(signal) }
|
140
141
|
end
|
@@ -171,13 +172,11 @@ module Resqued
|
|
171
172
|
def reap_workers(waitpidflags = 0)
|
172
173
|
loop do
|
173
174
|
worker_pid, status = Process.waitpid2(-1, waitpidflags)
|
174
|
-
if worker_pid.nil?
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
report_to_master("-#{worker_pid}")
|
180
|
-
end
|
175
|
+
return :none_ready if worker_pid.nil?
|
176
|
+
|
177
|
+
log "Worker exited #{status}"
|
178
|
+
finish_worker(worker_pid, status)
|
179
|
+
report_to_master("-#{worker_pid}")
|
181
180
|
end
|
182
181
|
rescue Errno::ECHILD
|
183
182
|
# All done
|
@@ -187,6 +186,7 @@ module Resqued
|
|
187
186
|
# Private: Check if master reports any dead workers.
|
188
187
|
def check_for_expired_workers
|
189
188
|
return unless @socket
|
189
|
+
|
190
190
|
loop do
|
191
191
|
IO.select([@socket], nil, nil, 0) or return
|
192
192
|
line = @socket.readline
|
@@ -210,11 +210,11 @@ module Resqued
|
|
210
210
|
# Private.
|
211
211
|
def start_idle_workers
|
212
212
|
workers.each do |worker|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
213
|
+
next unless worker.idle?
|
214
|
+
|
215
|
+
worker.try_start
|
216
|
+
if pid = worker.pid
|
217
|
+
report_to_master("+#{pid},#{worker.queue_key}")
|
218
218
|
end
|
219
219
|
end
|
220
220
|
end
|
@@ -236,7 +236,7 @@ module Resqued
|
|
236
236
|
# report_to_master("+12345,queue") # Worker process PID:12345 started, working on a job from "queue".
|
237
237
|
# report_to_master("-12345") # Worker process PID:12345 exited.
|
238
238
|
def report_to_master(status)
|
239
|
-
@socket
|
239
|
+
@socket&.puts(status)
|
240
240
|
rescue Errno::EPIPE => e
|
241
241
|
@socket = nil
|
242
242
|
log "#{e.class.name} while writing to master"
|