resque-director 1.0.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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +76 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/lib/resque/plugins/director/config.rb +39 -0
- data/lib/resque/plugins/director/lifecycle.rb +30 -0
- data/lib/resque/plugins/director/scaler.rb +72 -0
- data/lib/resque/plugins/director/worker_tracker.rb +57 -0
- data/lib/resque/plugins/director.rb +95 -0
- data/lib/resque-director.rb +7 -0
- data/resque-director.gemspec +76 -0
- data/spec/redis-test.conf +417 -0
- data/spec/resque/plugins/director/config_spec.rb +37 -0
- data/spec/resque/plugins/director/lifecycle_spec.rb +20 -0
- data/spec/resque/plugins/director/scaler_spec.rb +246 -0
- data/spec/resque/plugins/director/worker_tracker_spec.rb +137 -0
- data/spec/resque/plugins/director_spec.rb +200 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/test_job.rb +7 -0
- metadata +176 -0
@@ -0,0 +1,246 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Resque::Plugins::Director::Scaler do
|
4
|
+
subject { Resque::Plugins::Director::Scaler }
|
5
|
+
|
6
|
+
before do
|
7
|
+
Resque::Plugins::Director::Config.queue = "test"
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#scale_up" do
|
11
|
+
it "should start a worker on a specific queue" do
|
12
|
+
subject.should_receive(:system).with("QUEUE=test rake resque:work &")
|
13
|
+
subject.scale_up
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should start the specified number of workers on a specific queue" do
|
17
|
+
subject.should_receive(:system).twice.with("QUEUE=test rake resque:work &")
|
18
|
+
subject.scale_up(2)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not start more workers than the maximum allowed" do
|
22
|
+
Resque::Plugins::Director::Config.setup :max_workers => 1
|
23
|
+
subject.should_receive(:system).once.with("QUEUE=test rake resque:work &")
|
24
|
+
subject.scale_up(2)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should override the entire comand" do
|
28
|
+
Resque::Plugins::Director::Config.setup(:start_override => "run this")
|
29
|
+
subject.should_receive(:system).with("run this")
|
30
|
+
subject.scale_up
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#scaling" do
|
35
|
+
before do
|
36
|
+
@times_scaled = 0
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not scale workers if last time scaled is too soon" do
|
40
|
+
Resque::Plugins::Director::Config.setup(:wait_time => 60)
|
41
|
+
2.times { subject.scaling { @times_scaled += 1 } }
|
42
|
+
@times_scaled.should == 1
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should scale workers if wait time has passed" do
|
46
|
+
Resque::Plugins::Director::Config.setup(:wait_time => 0)
|
47
|
+
2.times { subject.scaling { @times_scaled += 1 } }
|
48
|
+
@times_scaled.should == 2
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#scale_down_to_minimum" do
|
53
|
+
before do
|
54
|
+
@worker = Resque::Worker.new(:test)
|
55
|
+
Resque::Plugins::Director::Config.setup :min_workers => 1
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should scale workers down to the minimum" do
|
59
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, @worker]
|
60
|
+
Process.should_receive(:kill).twice
|
61
|
+
subject.scale_down_to_minimum
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not scale if the workers are already at the minimum" do
|
65
|
+
Resque.should_receive(:workers).and_return [@worker]
|
66
|
+
Process.should_not_receive(:kill)
|
67
|
+
subject.scale_down_to_minimum
|
68
|
+
end
|
69
|
+
|
70
|
+
it "forces scaling by ignoring wait_time" do
|
71
|
+
Resque::Plugins::Director::Config.setup(:wait_time => 60, :min_workers => 2)
|
72
|
+
subject.scaling {}
|
73
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, @worker]
|
74
|
+
Process.should_receive(:kill)
|
75
|
+
subject.scale_down_to_minimum
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#scale_down" do
|
80
|
+
before do
|
81
|
+
@worker = Resque::Worker.new(:test)
|
82
|
+
Resque::Plugins::Director::Config.setup :min_workers => 0
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should scale down a single worker by default" do
|
86
|
+
worker2 = Resque::Worker.new(:test)
|
87
|
+
Resque.should_receive(:workers).and_return [@worker, worker2]
|
88
|
+
|
89
|
+
Process.should_receive(:kill).once
|
90
|
+
subject.scale_down
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should scale down multiple workers" do
|
94
|
+
worker2 = Resque::Worker.new(:test)
|
95
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, worker2]
|
96
|
+
[@worker, worker2].each { |w| Process.should_receive(:kill).with("QUIT", w.pid) }
|
97
|
+
subject.scale_down(2)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should not scale down more than the minimum allowed workers" do
|
101
|
+
Resque::Plugins::Director::Config.setup :min_workers => 1
|
102
|
+
|
103
|
+
Resque.should_receive(:workers).and_return [@worker, @worker]
|
104
|
+
Process.should_receive(:kill).once
|
105
|
+
subject.scale_down(2)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should not scale down workers on different queues" do
|
109
|
+
worker2 = Resque::Worker.new(:not_test)
|
110
|
+
@worker.stub(:pid => 1)
|
111
|
+
worker2.stub(:pid => 2)
|
112
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, worker2]
|
113
|
+
|
114
|
+
Process.should_not_receive(:kill).with("QUIT", worker2.pid)
|
115
|
+
Process.should_receive(:kill).with("QUIT", @worker.pid)
|
116
|
+
subject.scale_down
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "#stop" do
|
121
|
+
before do
|
122
|
+
@worker = Resque::Worker.new(:test)
|
123
|
+
Resque::Plugins::Director::Config.setup :min_workers => 0
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should kill worker by sending the QUIT signal to the workers pid" do
|
127
|
+
Resque.should_receive(:workers).and_return [@worker]
|
128
|
+
tracker = Resque::Plugins::Director::WorkerTracker.new
|
129
|
+
|
130
|
+
Process.should_receive(:kill).with("QUIT", @worker.pid)
|
131
|
+
subject.send(:stop, tracker, 1)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should use the stop command to stop a worker if set" do
|
135
|
+
Resque::Plugins::Director::Config.setup :stop_override => "run this", :min_workers => 0
|
136
|
+
Resque.should_receive(:workers).and_return [@worker]
|
137
|
+
tracker = Resque::Plugins::Director::WorkerTracker.new
|
138
|
+
|
139
|
+
subject.should_receive(:system).with("run this")
|
140
|
+
Process.should_not_receive(:kill)
|
141
|
+
subject.send(:stop, tracker, 1)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "does not stop workers already set to be shutdown" do
|
145
|
+
@worker.should_receive(:shutdown?).and_return(true)
|
146
|
+
Resque.should_receive(:workers).and_return [@worker]
|
147
|
+
tracker = Resque::Plugins::Director::WorkerTracker.new
|
148
|
+
|
149
|
+
Process.should_not_receive(:kill).with("QUIT", @worker.pid)
|
150
|
+
subject.send(:stop, tracker, 1)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "does not kill worker processes on different machines" do
|
154
|
+
@worker.stub!(:hostname => "different_machine")
|
155
|
+
Resque.should_receive(:workers).and_return [@worker]
|
156
|
+
tracker = Resque::Plugins::Director::WorkerTracker.new
|
157
|
+
|
158
|
+
Process.should_not_receive(:kill).with("QUIT", @worker.pid)
|
159
|
+
subject.send(:stop, tracker, 1)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "stops workers on the same host if possible" do
|
163
|
+
@worker.stub!(:hostname => "different_machine")
|
164
|
+
worker2 = Resque::Worker.new(:test)
|
165
|
+
Resque.should_receive(:workers).and_return [@worker, worker2]
|
166
|
+
tracker = Resque::Plugins::Director::WorkerTracker.new
|
167
|
+
|
168
|
+
Process.should_receive(:kill).with("QUIT", worker2.pid)
|
169
|
+
subject.send(:stop, tracker, 1)
|
170
|
+
end
|
171
|
+
|
172
|
+
it "ignores hostname if using custom stop script" do
|
173
|
+
Resque::Plugins::Director::Config.setup :stop_override => "run this", :min_workers => 0
|
174
|
+
@worker.stub!(:hostname => "different_machine")
|
175
|
+
Resque.should_receive(:workers).and_return [@worker]
|
176
|
+
tracker = Resque::Plugins::Director::WorkerTracker.new
|
177
|
+
|
178
|
+
subject.should_receive(:system).with("run this")
|
179
|
+
Process.should_not_receive(:kill)
|
180
|
+
subject.send(:stop, tracker, 1)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "#scale_within_requirements" do
|
185
|
+
it "should not scale up workers if the minumum number or greater are already running" do
|
186
|
+
Resque::Worker.new(:test).register_worker
|
187
|
+
subject.should_not_receive(:scale_up)
|
188
|
+
subject.scale_within_requirements
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should scale up the minimum number of workers if non are running" do
|
192
|
+
Resque::Plugins::Director::Config.setup :min_workers => 2
|
193
|
+
subject.should_receive(:scale_up).with(2)
|
194
|
+
subject.scale_within_requirements
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should ensure at least one worker is running if min_workers is less than zero" do
|
198
|
+
Resque::Plugins::Director::Config.setup :min_workers => -10
|
199
|
+
subject.should_receive(:scale_up).with(1)
|
200
|
+
subject.scale_within_requirements
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should ensure at least one worker is running if min_workers is zero" do
|
204
|
+
Resque::Plugins::Director::Config.setup :min_workers => 0
|
205
|
+
subject.should_receive(:scale_up).with(1)
|
206
|
+
subject.scale_within_requirements
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should scale up the minimum number of workers if less than the minimum are running" do
|
210
|
+
Resque::Plugins::Director::Config.setup :min_workers => 2
|
211
|
+
Resque::Worker.new(:test).register_worker
|
212
|
+
subject.should_receive(:scale_up).with(1)
|
213
|
+
subject.scale_within_requirements
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should scale down the max number of workers if more than max" do
|
217
|
+
Resque::Plugins::Director::Config.setup :max_workers => 1
|
218
|
+
workers = 2.times.map { Resque::Worker.new(:test) }
|
219
|
+
Resque.should_receive(:workers).and_return(workers)
|
220
|
+
|
221
|
+
subject.should_receive(:scale_down).with(1)
|
222
|
+
subject.scale_within_requirements
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should not scale down if max_workers is zero" do
|
226
|
+
Resque::Plugins::Director::Config.setup :max_workers => 0
|
227
|
+
workers = 1.times.map { Resque::Worker.new(:test) }
|
228
|
+
Resque.should_receive(:workers).and_return(workers)
|
229
|
+
|
230
|
+
subject.should_not_receive(:scale_down)
|
231
|
+
subject.scale_within_requirements
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should ignore workers from other queues" do
|
235
|
+
Resque::Worker.new(:other).register_worker
|
236
|
+
subject.should_receive(:scale_up).with(1)
|
237
|
+
subject.scale_within_requirements
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should ignore workers on multiple queues" do
|
241
|
+
Resque::Worker.new(:test, :other).register_worker
|
242
|
+
subject.should_receive(:scale_up).with(1)
|
243
|
+
subject.scale_within_requirements
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Resque::Plugins::Director::WorkerTracker do
|
4
|
+
subject { Resque::Plugins::Director::WorkerTracker }
|
5
|
+
|
6
|
+
before do
|
7
|
+
Resque::Plugins::Director::Config.queue = "test"
|
8
|
+
@worker = Resque::Worker.new(:test)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#workers" do
|
12
|
+
before do
|
13
|
+
Resque::Plugins::Director::Config.queue = "worker_test"
|
14
|
+
end
|
15
|
+
|
16
|
+
it"should return the workers for the queue" do
|
17
|
+
Resque::Worker.new(:other).register_worker
|
18
|
+
expected_worker = Resque::Worker.new(:worker_test)
|
19
|
+
expected_worker.register_worker
|
20
|
+
|
21
|
+
subject.new.workers.should == [expected_worker]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not return workers working on multiple queues" do
|
25
|
+
Resque::Worker.new(:worker_test, :other).register_worker
|
26
|
+
subject.new.workers.should be_empty
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#total_to_remove" do
|
31
|
+
it "should limit the workers to be removed to not go below minimum allowed workers" do
|
32
|
+
Resque.should_receive(:workers).and_return [@worker, @worker]
|
33
|
+
Resque::Plugins::Director::Config.setup :min_workers => 1
|
34
|
+
subject.new.total_to_remove(2).should == 1
|
35
|
+
end
|
36
|
+
|
37
|
+
it "always keeps at least one worker" do
|
38
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, @worker]
|
39
|
+
Resque::Plugins::Director::Config.setup :min_workers => 0
|
40
|
+
subject.new.total_to_remove(2).should == 2
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return zero if there is only one worker working" do
|
44
|
+
Resque.should_receive(:workers).and_return [@worker]
|
45
|
+
Resque::Plugins::Director::Config.setup :min_workers => 0
|
46
|
+
subject.new.total_to_remove(1).should == 0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
describe "#total_to_add" do
|
52
|
+
before do
|
53
|
+
Resque.should_receive(:workers).and_return [@worker, @worker]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should limit the workers to be removed to not go below minimum allowed workers" do
|
57
|
+
Resque::Plugins::Director::Config.setup :max_workers => 3
|
58
|
+
subject.new.total_to_add(2).should == 1
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should allow the workers to be removed if it stays above the minimum" do
|
62
|
+
Resque::Plugins::Director::Config.setup :max_workers => 4
|
63
|
+
subject.new.total_to_add(2).should == 2
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not limit workers added if max_workers is zero" do
|
67
|
+
Resque::Plugins::Director::Config.setup :max_workers => 0
|
68
|
+
subject.new.total_to_add(200).should == 200
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#total_for_requirements" do
|
73
|
+
it "should return the number of workers needed to meet the minimum requirement" do
|
74
|
+
Resque.should_receive(:workers).and_return [@worker, @worker]
|
75
|
+
Resque::Plugins::Director::Config.setup :min_workers => 4
|
76
|
+
subject.new.total_for_requirements.should == 2
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should return the number of workers needed to meet the maximum requirement" do
|
80
|
+
Resque.should_receive(:workers).and_return [@worker, @worker]
|
81
|
+
Resque::Plugins::Director::Config.setup :max_workers => 1
|
82
|
+
subject.new.total_for_requirements.should == -1
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return 1 no workers are running and the minimum is zero" do
|
86
|
+
Resque.should_receive(:workers).and_return []
|
87
|
+
Resque::Plugins::Director::Config.setup :min_workers => 0
|
88
|
+
subject.new.total_for_requirements.should == 1
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should return 0 if number of workers is within requirements" do
|
92
|
+
Resque.should_receive(:workers).and_return [@worker, @worker]
|
93
|
+
Resque::Plugins::Director::Config.setup :min_workers => 1, :max_workers => 3
|
94
|
+
subject.new.total_for_requirements.should == 0
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#total_to_go_to_minimum" do
|
99
|
+
it "should return the number to scale down to go to the minimum" do
|
100
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, @worker]
|
101
|
+
Resque::Plugins::Director::Config.setup :min_workers => 2
|
102
|
+
subject.new.total_to_go_to_minimum.should == 1
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should return zero if already at the minimum" do
|
106
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, @worker]
|
107
|
+
Resque::Plugins::Director::Config.setup :min_workers => 3
|
108
|
+
subject.new.total_to_go_to_minimum.should == 0
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should return zero if below the minimum" do
|
112
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, @worker]
|
113
|
+
Resque::Plugins::Director::Config.setup :min_workers => 4
|
114
|
+
subject.new.total_to_go_to_minimum.should == 0
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "#initialize" do
|
119
|
+
it "sets the workers from the queue" do
|
120
|
+
Resque.should_receive(:workers).and_return [@worker, @worker, @worker]
|
121
|
+
subject.new.workers.should == [@worker, @worker, @worker]
|
122
|
+
end
|
123
|
+
|
124
|
+
it "does not set workers from different queues" do
|
125
|
+
other_worker = Resque::Worker.new(:other)
|
126
|
+
Resque.should_receive(:workers).and_return [@worker, other_worker, @worker]
|
127
|
+
subject.new.workers.should == [@worker, @worker]
|
128
|
+
end
|
129
|
+
|
130
|
+
it "does not set workers that are scheduled for shutdow" do
|
131
|
+
shutdown_worker = Resque::Worker.new(:test)
|
132
|
+
shutdown_worker.shutdown
|
133
|
+
Resque.should_receive(:workers).and_return [shutdown_worker, @worker, @worker]
|
134
|
+
subject.new.workers.should == [@worker, @worker]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Resque::Plugins::Director do
|
4
|
+
before do
|
5
|
+
TestJob.direct
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be a valid resque plugin" do
|
9
|
+
Resque::Plugin.lint(Resque::Plugins::Director)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#after_enqueue_scale_workers" do
|
13
|
+
it "should scale the workers to within the requirments specified" do
|
14
|
+
Resque::Worker.new(:test).register_worker
|
15
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_within_requirements)
|
16
|
+
Resque.enqueue(TestJob)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should set the queue" do
|
20
|
+
Resque.enqueue(TestJob)
|
21
|
+
Resque::Plugins::Director::Config.queue.should == "test"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#after_perform_direct_workers" do
|
26
|
+
it "should scale down to the minumum workers if there are no jobs in the queue" do
|
27
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_down_to_minimum)
|
28
|
+
TestJob.after_perform_direct_workers
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not scale down if there are jobs in the queue" do
|
32
|
+
Resque.enqueue(TestJob)
|
33
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_down_to_minimum)
|
34
|
+
TestJob.after_perform_direct_workers
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#on_failure_direct_workers" do
|
39
|
+
it "should scale down to the minumum workers if there are no jobs in the queue" do
|
40
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_down_to_minimum)
|
41
|
+
TestJob.on_failure_direct_workers
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not scale down if there are jobs in the queue" do
|
45
|
+
Resque.enqueue(TestJob)
|
46
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_down_to_minimum)
|
47
|
+
TestJob.on_failure_direct_workers
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#before_perform_direct_workers" do
|
52
|
+
describe "with time" do
|
53
|
+
before do
|
54
|
+
@start_time = {:resdirecttime => (Time.now - 10).utc.to_i}
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should set the queue if not set" do
|
58
|
+
TestJob.direct :max_time => 20
|
59
|
+
Resque::Plugins::Director::Config.queue = nil
|
60
|
+
TestJob.before_perform_direct_workers(@start_time)
|
61
|
+
Resque::Plugins::Director::Config.queue.should == "test"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not start workers if max_time is not set" do
|
65
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_up)
|
66
|
+
TestJob.before_perform_direct_workers(@start_time)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not start a worker if the time since it took is less than max_time" do
|
70
|
+
TestJob.direct :max_time => 20
|
71
|
+
|
72
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_up)
|
73
|
+
TestJob.before_perform_direct_workers(@start_time)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should add a worker if the time it takes the job to go through the queue is too long" do
|
77
|
+
TestJob.direct :max_time => 5
|
78
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_up)
|
79
|
+
|
80
|
+
TestJob.before_perform_direct_workers(@start_time)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should remove a worker if the queue time is below half the max" do
|
84
|
+
TestJob.direct :max_time => 25
|
85
|
+
|
86
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_down)
|
87
|
+
TestJob.before_perform_direct_workers(@start_time)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "with queue length" do
|
92
|
+
it "should not start workers if max_queue is not set" do
|
93
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_up)
|
94
|
+
TestJob.before_perform_direct_workers
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should not start worker if the queue length is less than max_queue" do
|
98
|
+
TestJob.direct :max_queue => 2
|
99
|
+
Resque.enqueue(TestJob)
|
100
|
+
|
101
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_up)
|
102
|
+
TestJob.before_perform_direct_workers
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should start worker if the queue length is greater than max_queue" do
|
106
|
+
TestJob.direct :max_queue => 1
|
107
|
+
2.times { Resque.enqueue(TestJob) }
|
108
|
+
|
109
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_up)
|
110
|
+
TestJob.before_perform_direct_workers
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should remove a worker if the queue length is below half the max" do
|
114
|
+
TestJob.direct :max_queue => 4
|
115
|
+
1.times { Resque.enqueue(TestJob) }
|
116
|
+
|
117
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_down)
|
118
|
+
TestJob.before_perform_direct_workers
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "with length and time" do
|
123
|
+
|
124
|
+
before do
|
125
|
+
@start_time = {:resdirecttime => (Time.now - 10).utc.to_i}
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should add worker if only time constraint fails" do
|
129
|
+
TestJob.direct :max_time => 5, :max_queue => 2
|
130
|
+
Resque.enqueue(TestJob)
|
131
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_up)
|
132
|
+
|
133
|
+
TestJob.before_perform_direct_workers(@start_time)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should add worker if only queue length constraint fails" do
|
137
|
+
TestJob.direct :max_time => 15, :max_queue => 1
|
138
|
+
2.times { Resque.enqueue(TestJob) }
|
139
|
+
|
140
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_up)
|
141
|
+
TestJob.before_perform_direct_workers
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should not scale down if a worker is being scaled up due to time" do
|
145
|
+
TestJob.direct :max_queue => 4, :max_time => 5
|
146
|
+
1.times { Resque.enqueue(TestJob) }
|
147
|
+
|
148
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_up)
|
149
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_down)
|
150
|
+
TestJob.before_perform_direct_workers(@start_time)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should not scale down if a worker is being scaled up due to queue" do
|
154
|
+
TestJob.direct :max_queue => 1, :max_time => 30
|
155
|
+
2.times { Resque.enqueue(TestJob) }
|
156
|
+
|
157
|
+
Resque::Plugins::Director::Scaler.should_receive(:scale_up)
|
158
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_down)
|
159
|
+
TestJob.before_perform_direct_workers
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should not scale if only one limit is met" do
|
163
|
+
TestJob.direct :max_queue => 3, :max_time => 15
|
164
|
+
1.times { Resque.enqueue(TestJob) }
|
165
|
+
|
166
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_up)
|
167
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_down)
|
168
|
+
TestJob.before_perform_direct_workers(@start_time)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should not scale if no configuration options are set" do
|
172
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_up)
|
173
|
+
Resque::Plugins::Director::Scaler.should_not_receive(:scale_down)
|
174
|
+
TestJob.before_perform_direct_workers
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "crazy meta custom_perform" do
|
179
|
+
it "should strip out the timestamp from the args before calling the original perform" do
|
180
|
+
TestJob.should_receive(:original_perform).with("arg")
|
181
|
+
TestJob.perform("arg", {:resdirecttime => 1234})
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should strip out timestamp if it is not a symbol" do
|
185
|
+
TestJob.should_receive(:original_perform).with("arg")
|
186
|
+
TestJob.perform("arg", {'resdirecttime' => 1234})
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should not strip out any args if timestamp does not exist" do
|
190
|
+
TestJob.should_receive(:original_perform).with("arg", {:test => 123})
|
191
|
+
TestJob.perform("arg", {:test => 123})
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should not strip out any args if timestamp does not exist" do
|
195
|
+
TestJob.should_receive(:original_perform).with("arg")
|
196
|
+
TestJob.perform("arg")
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'resque'
|
5
|
+
require 'resque-director'
|
6
|
+
|
7
|
+
# Requires supporting files with custom matchers and macros, etc,
|
8
|
+
# in ./support/ and its subdirectories.
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
10
|
+
|
11
|
+
#
|
12
|
+
# make sure we can run redis
|
13
|
+
#
|
14
|
+
if !system("which redis-server")
|
15
|
+
puts '', "** can't find `redis-server` in your path"
|
16
|
+
puts "** add redis-server to your PATH and try again"
|
17
|
+
abort ''
|
18
|
+
end
|
19
|
+
|
20
|
+
dir = File.dirname(__FILE__)
|
21
|
+
#
|
22
|
+
# start our own redis when the tests start,
|
23
|
+
# kill it when they end
|
24
|
+
#
|
25
|
+
|
26
|
+
at_exit do
|
27
|
+
pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0]
|
28
|
+
puts "Killing test redis server [#{pid}]..."
|
29
|
+
`rm -f #{dir}/dump.rdb`
|
30
|
+
Process.kill("KILL", pid.to_i)
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "Starting redis for testing at localhost:9736..."
|
34
|
+
`redis-server #{dir}/redis-test.conf`
|
35
|
+
Resque.redis = 'localhost:9736'
|
36
|
+
ENV['VERBOSE'] = 'true'
|
37
|
+
|
38
|
+
RSpec.configure do |config|
|
39
|
+
config.before(:each) do
|
40
|
+
Resque::Plugins::Director::Config.reset!
|
41
|
+
Resque::Plugins::Director::Scaler.stub!(:system)
|
42
|
+
Process.stub!(:kill)
|
43
|
+
Resque.redis.flushall
|
44
|
+
end
|
45
|
+
end
|