resqued 0.9.0 → 0.10.0
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 +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
@@ -0,0 +1,73 @@
|
|
1
|
+
module Resqued
|
2
|
+
class MasterState
|
3
|
+
def initialize
|
4
|
+
@listeners_created = 0
|
5
|
+
@listener_states = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
# Public: When starting fresh, from command-line options, assign the initial values.
|
9
|
+
def init(options)
|
10
|
+
@config_paths = options.fetch(:config_paths)
|
11
|
+
@exec_on_hup = options.fetch(:exec_on_hup, false)
|
12
|
+
@fast_exit = options.fetch(:fast_exit, false)
|
13
|
+
@pidfile = options.fetch(:master_pidfile, nil)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Restore state from a serialized form.
|
17
|
+
def restore(data)
|
18
|
+
@config_paths = data[:config_paths]
|
19
|
+
@current_listener_pid = data[:current_listener_pid]
|
20
|
+
@exec_on_hup = data[:exec_on_hup]
|
21
|
+
@fast_exit = data[:fast_exit]
|
22
|
+
@last_good_listener_pid = data[:last_good_listener_pid]
|
23
|
+
@listeners_created = data[:listeners_created]
|
24
|
+
data[:listener_states].each do |lsh|
|
25
|
+
@listener_states[lsh[:pid]] = ListenerState.new.tap do |ls|
|
26
|
+
ls.master_socket = lsh[:master_socket] && Socket.for_fd(lsh[:master_socket])
|
27
|
+
ls.options = lsh[:options]
|
28
|
+
ls.pid = lsh[:pid]
|
29
|
+
ls.worker_pids = lsh[:worker_pids]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
@paused = data[:paused]
|
33
|
+
@pidfile = data[:pidfile]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Public: Return this state so that it can be serialized.
|
37
|
+
def to_h
|
38
|
+
{
|
39
|
+
config_paths: @config_paths,
|
40
|
+
current_listener_pid: @current_listener_pid,
|
41
|
+
exec_on_hup: @exec_on_hup,
|
42
|
+
fast_exit: @fast_exit,
|
43
|
+
last_good_listener_pid: @last_good_listener_pid,
|
44
|
+
listeners_created: @listeners_created,
|
45
|
+
listener_states: @listener_states.values.map { |ls|
|
46
|
+
{
|
47
|
+
master_socket: ls.master_socket&.to_i,
|
48
|
+
options: ls.options,
|
49
|
+
pid: ls.pid,
|
50
|
+
worker_pids: ls.worker_pids,
|
51
|
+
}
|
52
|
+
},
|
53
|
+
paused: @paused,
|
54
|
+
pidfile: @pidfile,
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Return an array of open sockets or other file handles that should be forwarded to a new master.
|
59
|
+
def sockets
|
60
|
+
@listener_states.values.map { |l| l.master_socket }.compact
|
61
|
+
end
|
62
|
+
|
63
|
+
attr_reader :config_paths
|
64
|
+
attr_accessor :current_listener_pid
|
65
|
+
attr_reader :exec_on_hup
|
66
|
+
attr_reader :fast_exit
|
67
|
+
attr_accessor :last_good_listener_pid
|
68
|
+
attr_accessor :listeners_created
|
69
|
+
attr_reader :listener_states
|
70
|
+
attr_accessor :paused
|
71
|
+
attr_reader :pidfile
|
72
|
+
end
|
73
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "resqued/version"
|
2
2
|
|
3
3
|
module Resqued
|
4
4
|
module ProclineVersion
|
@@ -6,7 +6,7 @@ module Resqued
|
|
6
6
|
@version ||=
|
7
7
|
begin
|
8
8
|
# If we've built a custom version, this should show the custom version.
|
9
|
-
Gem.loaded_specs[
|
9
|
+
Gem.loaded_specs["resqued"].version.to_s
|
10
10
|
rescue Object
|
11
11
|
# If this isn't a gem, fall back to the version in resqued/version.rb.
|
12
12
|
Resqued::VERSION
|
data/lib/resqued/sleepy.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "fcntl"
|
2
|
+
require "kgio"
|
3
3
|
|
4
4
|
module Resqued
|
5
5
|
module Sleepy
|
6
|
-
# Public: Like sleep, but the sleep is interrupted if input is
|
6
|
+
# Public: Like sleep, but the sleep is interrupted if input is
|
7
|
+
# detected on one of the provided IO objects, or if `awake` is
|
8
|
+
# called (e.g. from a signal handler).
|
7
9
|
def yawn(duration, *inputs)
|
8
10
|
if duration > 0
|
9
11
|
inputs = [self_pipe[0]] + [inputs].flatten.compact
|
@@ -14,7 +16,7 @@ module Resqued
|
|
14
16
|
|
15
17
|
# Public: Break out of `yawn`.
|
16
18
|
def awake
|
17
|
-
self_pipe[1].kgio_trywrite(
|
19
|
+
self_pipe[1].kgio_trywrite(".")
|
18
20
|
end
|
19
21
|
|
20
22
|
# Private.
|
data/lib/resqued/test_case.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "resqued/config"
|
2
|
+
require "resqued/runtime_info"
|
3
3
|
|
4
4
|
module Resqued
|
5
5
|
module TestCase
|
@@ -17,7 +17,7 @@ module Resqued
|
|
17
17
|
config = Resqued::Config.new(paths)
|
18
18
|
config.before_fork(RuntimeInfo.new)
|
19
19
|
config.build_workers
|
20
|
-
config.after_fork(Resque::Worker.new(
|
20
|
+
config.after_fork(Resque::Worker.new("*"))
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
data/lib/resqued/version.rb
CHANGED
data/lib/resqued/worker.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "resque"
|
2
|
+
require "digest"
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
4
|
+
require "resqued/backoff"
|
5
|
+
require "resqued/logging"
|
6
6
|
|
7
7
|
module Resqued
|
8
8
|
# Models a worker process.
|
9
9
|
class Worker
|
10
10
|
include Resqued::Logging
|
11
11
|
|
12
|
-
DEFAULT_WORKER_FACTORY =
|
12
|
+
DEFAULT_WORKER_FACTORY = lambda { |queues|
|
13
13
|
resque_worker = Resque::Worker.new(*queues)
|
14
|
-
resque_worker.term_child = true if resque_worker.respond_to?(
|
14
|
+
resque_worker.term_child = true if resque_worker.respond_to?("term_child=")
|
15
15
|
redis_client = Resque.redis.respond_to?(:_client) ? Resque.redis._client : Resque.redis.client
|
16
16
|
redis_client.reconnect
|
17
17
|
resque_worker
|
@@ -44,12 +44,13 @@ module Resqued
|
|
44
44
|
|
45
45
|
# Public: A string that compares if this worker is equivalent to a worker in another Resqued::Listener.
|
46
46
|
def queue_key
|
47
|
-
Digest::SHA256.hexdigest(queues.sort.join(
|
47
|
+
Digest::SHA256.hexdigest(queues.sort.join(";"))
|
48
48
|
end
|
49
49
|
|
50
50
|
# Public: Claim this worker for another listener's worker.
|
51
51
|
def wait_for(pid)
|
52
52
|
raise "Already running #{@pid} (can't wait for #{pid})" if @pid
|
53
|
+
|
53
54
|
@self_started = false
|
54
55
|
@pids << pid
|
55
56
|
@pid = pid
|
@@ -57,16 +58,17 @@ module Resqued
|
|
57
58
|
|
58
59
|
# Public: The old worker process finished!
|
59
60
|
def finished!(process_status)
|
60
|
-
|
61
|
-
|
61
|
+
summary = "(#{@pid}/#{@pids.inspect}/self_started=#{@self_started}/killed=#{@killed})"
|
62
|
+
if process_status.nil? && !@self_started
|
63
|
+
log :debug, "#{summary} I am no longer blocked."
|
62
64
|
@pid = nil
|
63
65
|
@backoff.died unless @killed
|
64
|
-
elsif !
|
65
|
-
log :debug, "
|
66
|
+
elsif !process_status.nil? && @self_started
|
67
|
+
log :debug, "#{summary} I exited: #{process_status}"
|
66
68
|
@pid = nil
|
67
69
|
@backoff.died unless @killed
|
68
70
|
else
|
69
|
-
log :debug, "
|
71
|
+
log :debug, "#{summary} Reports of my death are highly exaggerated (#{process_status.inspect})"
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
@@ -78,6 +80,7 @@ module Resqued
|
|
78
80
|
# Public: Start a job, if there's one waiting in one of my queues.
|
79
81
|
def try_start
|
80
82
|
return if @backoff.wait?
|
83
|
+
|
81
84
|
@backoff.started
|
82
85
|
@self_started = true
|
83
86
|
@killed = false
|
@@ -87,7 +90,7 @@ module Resqued
|
|
87
90
|
log "Forked worker #{@pid}"
|
88
91
|
else
|
89
92
|
# In case we get a signal before resque is ready for it.
|
90
|
-
Resqued::Listener::ALL_SIGNALS.each { |signal| trap(signal,
|
93
|
+
Resqued::Listener::ALL_SIGNALS.each { |signal| trap(signal, "DEFAULT") }
|
91
94
|
trap(:QUIT) { exit! 0 } # If we get a QUIT during boot, just spin back down.
|
92
95
|
$0 = "STARTING RESQUE FOR #{queues.join(',')}"
|
93
96
|
resque_worker = @worker_factory.call(queues)
|
@@ -1,53 +1,53 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
|
-
require
|
3
|
+
require "resqued/backoff"
|
4
4
|
|
5
5
|
describe Resqued::Backoff do
|
6
|
-
let(:backoff) { described_class.new(:
|
6
|
+
let(:backoff) { described_class.new(min: 0.5, max: 64.0) }
|
7
7
|
|
8
|
-
it
|
8
|
+
it "can start on the first try" do
|
9
9
|
expect(backoff.wait?).to be_false
|
10
10
|
end
|
11
11
|
|
12
|
-
it
|
12
|
+
it "has no waiting at first" do
|
13
13
|
expect(backoff.how_long?).to be_nil
|
14
14
|
end
|
15
15
|
|
16
|
-
context
|
16
|
+
context "after expected exits" do
|
17
17
|
before { 3.times { backoff.started } }
|
18
18
|
it { expect(backoff.wait?).to be_true }
|
19
19
|
it { expect(backoff.how_long?).to be_close_to(0.5) }
|
20
20
|
end
|
21
21
|
|
22
|
-
context
|
23
|
-
before { 1.times { backoff.started
|
22
|
+
context "after one quick exit" do
|
23
|
+
before { 1.times { backoff.started; backoff.died } }
|
24
24
|
it { expect(backoff.wait?).to be_true }
|
25
25
|
it { expect(backoff.how_long?).to be_close_to(1.0) }
|
26
26
|
end
|
27
27
|
|
28
|
-
context
|
29
|
-
before { 2.times { backoff.started
|
28
|
+
context "after two quick starts" do
|
29
|
+
before { 2.times { backoff.started; backoff.died } }
|
30
30
|
it { expect(backoff.wait?).to be_true }
|
31
31
|
it { expect(backoff.how_long?).to be_close_to(2.0) }
|
32
32
|
end
|
33
33
|
|
34
|
-
context
|
35
|
-
before { 6.times { backoff.started
|
34
|
+
context "after five quick starts" do
|
35
|
+
before { 6.times { backoff.started; backoff.died } }
|
36
36
|
it { expect(backoff.wait?).to be_true }
|
37
37
|
it { expect(backoff.how_long?).to be_close_to(32.0) }
|
38
38
|
end
|
39
39
|
|
40
|
-
context
|
41
|
-
before { 7.times { backoff.started
|
40
|
+
context "after six quick starts" do
|
41
|
+
before { 7.times { backoff.started; backoff.died } }
|
42
42
|
it { expect(backoff.wait?).to be_true }
|
43
43
|
it { expect(backoff.how_long?).to be_close_to(64.0) }
|
44
44
|
end
|
45
45
|
|
46
|
-
context
|
47
|
-
before { 8.times { backoff.started
|
46
|
+
context "does not wait longer than 64s" do
|
47
|
+
before { 8.times { backoff.started; backoff.died } }
|
48
48
|
it { expect(backoff.wait?).to be_true }
|
49
49
|
it { expect(backoff.how_long?).to be_close_to(64.0) }
|
50
|
-
it
|
50
|
+
it "and resets after an expected exit" do
|
51
51
|
backoff.started
|
52
52
|
backoff.started
|
53
53
|
expect(backoff.wait?).to be_true
|
@@ -55,7 +55,7 @@ describe Resqued::Backoff do
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
def be_close_to(
|
59
|
-
be_within(0.005).of(
|
58
|
+
def be_close_to(number)
|
59
|
+
be_within(0.005).of(number)
|
60
60
|
end
|
61
61
|
end
|
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "spec_helper"
|
2
|
+
require "resqued/config/after_fork"
|
3
|
+
require "resqued/config/before_fork"
|
4
|
+
require "resqued/runtime_info"
|
5
5
|
|
6
6
|
describe do
|
7
7
|
before { evaluator.apply(config) }
|
8
8
|
|
9
|
-
context
|
9
|
+
context "after_fork" do
|
10
10
|
# Run the after_fork block.
|
11
11
|
#
|
12
12
|
# after_fork do |resque_worker|
|
@@ -26,13 +26,13 @@ describe do
|
|
26
26
|
end
|
27
27
|
END_CONFIG
|
28
28
|
|
29
|
-
let(:evaluator) { Resqued::Config::AfterFork.new(:
|
29
|
+
let(:evaluator) { Resqued::Config::AfterFork.new(worker: worker) }
|
30
30
|
let(:worker) { FakeResqueWorker.new }
|
31
31
|
|
32
32
|
it { expect(worker.token).to eq(:called) }
|
33
33
|
end
|
34
34
|
|
35
|
-
context
|
35
|
+
context "before_fork" do
|
36
36
|
# Run the before_fork block.
|
37
37
|
#
|
38
38
|
# before_fork do
|
@@ -56,7 +56,7 @@ describe do
|
|
56
56
|
end
|
57
57
|
END_CONFIG
|
58
58
|
|
59
|
-
let(:evaluator) { $before_fork_called = false
|
59
|
+
let(:evaluator) { $before_fork_called = false; Resqued::Config::BeforeFork.new(resqued: resqued) }
|
60
60
|
let(:resqued) { Resqued::RuntimeInfo.new }
|
61
61
|
|
62
62
|
it { expect($before_fork_called).to eq(true) }
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "spec_helper"
|
2
|
+
require "resqued/config/worker"
|
3
3
|
|
4
4
|
describe Resqued::Config::Worker do
|
5
5
|
# Create a bunch of Resqued::Worker objects from
|
@@ -15,7 +15,7 @@ describe Resqued::Config::Worker do
|
|
15
15
|
#
|
16
16
|
# ignore calls to any other top-level method.
|
17
17
|
|
18
|
-
let(:evaluator) { described_class.new(:
|
18
|
+
let(:evaluator) { described_class.new(worker_class: FakeWorker) }
|
19
19
|
let(:result) { evaluator.apply(config) }
|
20
20
|
module FakeWorker
|
21
21
|
def self.new(options)
|
@@ -23,7 +23,7 @@ describe Resqued::Config::Worker do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
context
|
26
|
+
context "individual" do
|
27
27
|
let(:config) { <<-END_CONFIG }
|
28
28
|
before_fork { }
|
29
29
|
after_fork { }
|
@@ -35,25 +35,27 @@ describe Resqued::Config::Worker do
|
|
35
35
|
after_fork { } # So that we don't rely on `workers`'s result falling through.
|
36
36
|
END_CONFIG
|
37
37
|
it { expect(result.size).to eq(6) }
|
38
|
-
it { expect(result[0]).to eq(:
|
39
|
-
it { expect(result[1]).to eq(:
|
40
|
-
it { expect(result[2]).to eq(:
|
41
|
-
it { expect(result[3]).to eq(:
|
42
|
-
it { expect(result[4]).to eq(:
|
43
|
-
it { expect(result[5]).to eq(:
|
38
|
+
it { expect(result[0]).to eq(queues: ["a"]) }
|
39
|
+
it { expect(result[1]).to eq(queues: ["a"]) }
|
40
|
+
it { expect(result[2]).to eq(queues: ["b"]) }
|
41
|
+
it { expect(result[3]).to eq(queues: ["c", "d"]) }
|
42
|
+
it { expect(result[4]).to eq(queues: ["d", "c"], interval: 3) }
|
43
|
+
it { expect(result[5]).to eq(queues: ["*"]) }
|
44
44
|
end
|
45
45
|
|
46
|
-
context
|
46
|
+
context "concise pool" do
|
47
47
|
let(:config) { <<-END_CONFIG }
|
48
48
|
worker_pool 2, 'a', 'b', 'c', :interval => 1
|
49
49
|
END_CONFIG
|
50
|
-
it
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
it do
|
51
|
+
expect(result).to eq([
|
52
|
+
{ queues: ["a", "b", "c"], interval: 1 },
|
53
|
+
{ queues: ["a", "b", "c"], interval: 1 },
|
54
|
+
])
|
55
|
+
end
|
54
56
|
end
|
55
57
|
|
56
|
-
context
|
58
|
+
context "pool (hash for concurrency)" do
|
57
59
|
let(:config) { <<-END_CONFIG }
|
58
60
|
before_fork { }
|
59
61
|
after_fork { }
|
@@ -64,15 +66,15 @@ describe Resqued::Config::Worker do
|
|
64
66
|
after_fork { } # So that we don't rely on `worker_pool`'s result falling through.
|
65
67
|
END_CONFIG
|
66
68
|
it { expect(result.size).to eq(20) }
|
67
|
-
it { expect(result[0]).to eq(:
|
68
|
-
it { expect(result[3]).to eq(:
|
69
|
-
it { expect(result[4]).to eq(:
|
70
|
-
it { expect(result[9]).to eq(:
|
71
|
-
it { expect(result[10]).to eq(:
|
72
|
-
it { expect(result[19]).to eq(:
|
69
|
+
it { expect(result[0]).to eq(queues: ["a", "b1", "b2", "c"], interval: 1) }
|
70
|
+
it { expect(result[3]).to eq(queues: ["a", "b1", "b2", "c"], interval: 1) }
|
71
|
+
it { expect(result[4]).to eq(queues: ["b1", "b2", "c"], interval: 1) }
|
72
|
+
it { expect(result[9]).to eq(queues: ["b1", "b2", "c"], interval: 1) }
|
73
|
+
it { expect(result[10]).to eq(queues: ["c"], interval: 1) }
|
74
|
+
it { expect(result[19]).to eq(queues: ["c"], interval: 1) }
|
73
75
|
end
|
74
76
|
|
75
|
-
context
|
77
|
+
context "pool, with implied queue" do
|
76
78
|
let(:config) { <<-END_CONFIG }
|
77
79
|
before_fork { }
|
78
80
|
after_fork { }
|
@@ -80,11 +82,11 @@ describe Resqued::Config::Worker do
|
|
80
82
|
after_fork { } # So that we don't rely on `worker_pool`'s result falling through.
|
81
83
|
END_CONFIG
|
82
84
|
it { expect(result.size).to eq(20) }
|
83
|
-
it { expect(result[0]).to eq(:
|
84
|
-
it { expect(result[19]).to eq(:
|
85
|
+
it { expect(result[0]).to eq(queues: ["*"]) }
|
86
|
+
it { expect(result[19]).to eq(queues: ["*"]) }
|
85
87
|
end
|
86
88
|
|
87
|
-
context
|
89
|
+
context "pool, with fewer queues than workers" do
|
88
90
|
let(:config) { <<-END_CONFIG }
|
89
91
|
before_fork { }
|
90
92
|
after_fork { }
|
@@ -93,13 +95,13 @@ describe Resqued::Config::Worker do
|
|
93
95
|
after_fork { } # So that we don't rely on `worker_pool`'s result falling through.
|
94
96
|
END_CONFIG
|
95
97
|
it { expect(result.size).to eq(20) }
|
96
|
-
it { expect(result[0]).to eq(:
|
97
|
-
it { expect(result[9]).to eq(:
|
98
|
-
it { expect(result[10]).to eq(:
|
99
|
-
it { expect(result[19]).to eq(:
|
98
|
+
it { expect(result[0]).to eq(queues: ["a"]) }
|
99
|
+
it { expect(result[9]).to eq(queues: ["a"]) }
|
100
|
+
it { expect(result[10]).to eq(queues: ["*"]) }
|
101
|
+
it { expect(result[19]).to eq(queues: ["*"]) }
|
100
102
|
end
|
101
103
|
|
102
|
-
context
|
104
|
+
context "pool, with more queues than workers" do
|
103
105
|
let(:config) { <<-END_CONFIG }
|
104
106
|
before_fork { }
|
105
107
|
after_fork { }
|
@@ -110,48 +112,48 @@ describe Resqued::Config::Worker do
|
|
110
112
|
it { expect(result.size).to eq(20) }
|
111
113
|
end
|
112
114
|
|
113
|
-
context
|
115
|
+
context "pool, with shuffled queues" do
|
114
116
|
let(:config) { <<-END_CONFIG }
|
115
117
|
worker_pool 20, :shuffle_queues => true
|
116
118
|
queue 'a', :count => 10
|
117
119
|
queue 'b', :count => 15
|
118
120
|
END_CONFIG
|
119
121
|
it { expect(result.size).to eq(20) }
|
120
|
-
it { (0..9).each { |i| expect(result[i][:queues].sort).to eq([
|
121
|
-
it { (10..14).each { |i| expect(result[i][:queues]).to eq([
|
122
|
-
it { (15..19).each { |i| expect(result[i][:queues]).to eq([
|
122
|
+
it { (0..9).each { |i| expect(result[i][:queues].sort).to eq(["a", "b"]) } }
|
123
|
+
it { (10..14).each { |i| expect(result[i][:queues]).to eq(["b"]) } }
|
124
|
+
it { (15..19).each { |i| expect(result[i][:queues]).to eq(["*"]) } }
|
123
125
|
it { result.each { |x| expect(x).not_to have_key(:shuffle_queues) } }
|
124
126
|
it do
|
125
127
|
shuffled_queues = result.take(10).map { |x| x[:queues] }
|
126
|
-
expect(shuffled_queues.sort.uniq).to eq([
|
128
|
+
expect(shuffled_queues.sort.uniq).to eq([["a", "b"], ["b", "a"]]) # Some of the queues should be shuffled
|
127
129
|
end
|
128
130
|
end
|
129
131
|
|
130
|
-
context
|
132
|
+
context "multiple worker configs" do
|
131
133
|
let(:config) { <<-END_CONFIG }
|
132
134
|
worker 'one'
|
133
135
|
worker 'two'
|
134
136
|
worker_pool 2
|
135
137
|
END_CONFIG
|
136
138
|
it { expect(result.size).to eq(4) }
|
137
|
-
it { expect(result[0]).to eq(:
|
138
|
-
it { expect(result[1]).to eq(:
|
139
|
-
it { expect(result[2]).to eq(:
|
140
|
-
it { expect(result[3]).to eq(:
|
139
|
+
it { expect(result[0]).to eq(queues: ["one"]) }
|
140
|
+
it { expect(result[1]).to eq(queues: ["two"]) }
|
141
|
+
it { expect(result[2]).to eq(queues: ["*"]) }
|
142
|
+
it { expect(result[3]).to eq(queues: ["*"]) }
|
141
143
|
end
|
142
144
|
|
143
|
-
context
|
145
|
+
context "worker factory" do
|
144
146
|
let(:config) { <<-END_CONFIG }
|
145
147
|
worker_factory { |queues| queues }
|
146
148
|
worker 'a'
|
147
149
|
END_CONFIG
|
148
150
|
|
149
151
|
it { expect(result.size).to eq(1) }
|
150
|
-
it { expect(result[0].reject { |k, _| k == :worker_factory}).to eq(:
|
151
|
-
it { expect(result[0][:worker_factory].call(result[0][:queues])).to eq([
|
152
|
+
it { expect(result[0].reject { |k, _| k == :worker_factory }).to eq(queues: ["a"]) }
|
153
|
+
it { expect(result[0][:worker_factory].call(result[0][:queues])).to eq(["a"]) }
|
152
154
|
end
|
153
155
|
|
154
|
-
context
|
156
|
+
context "worker factory with pool" do
|
155
157
|
let(:config) { <<-END_CONFIG }
|
156
158
|
worker_factory { |queues| queues }
|
157
159
|
worker_pool 1
|
@@ -159,15 +161,15 @@ describe Resqued::Config::Worker do
|
|
159
161
|
END_CONFIG
|
160
162
|
|
161
163
|
it { expect(result.size).to eq(1) }
|
162
|
-
it { expect(result[0].reject { |k, _| k == :worker_factory}).to eq(:
|
163
|
-
it { expect(result[0][:worker_factory].call(result[0][:queues])).to eq([
|
164
|
+
it { expect(result[0].reject { |k, _| k == :worker_factory }).to eq(queues: ["a"]) }
|
165
|
+
it { expect(result[0][:worker_factory].call(result[0][:queues])).to eq(["a"]) }
|
164
166
|
end
|
165
167
|
|
166
|
-
context
|
167
|
-
let(:evaluator) { described_class.new(:
|
168
|
+
context "with default options" do
|
169
|
+
let(:evaluator) { described_class.new(worker_class: FakeWorker, config: "something") }
|
168
170
|
let(:config) { <<-END_CONFIG }
|
169
171
|
worker 'a', :interval => 1
|
170
172
|
END_CONFIG
|
171
|
-
it { expect(result[0]).to eq(:
|
173
|
+
it { expect(result[0]).to eq(queues: ["a"], interval: 1, config: "something") }
|
172
174
|
end
|
173
175
|
end
|