delayed_job_with_named_queues 2.0.7.1
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/MIT-LICENSE +20 -0
- data/README.textile +248 -0
- data/contrib/delayed_job.monitrc +14 -0
- data/contrib/delayed_job_multiple.monitrc +23 -0
- data/generators/delayed_job/delayed_job_generator.rb +22 -0
- data/generators/delayed_job/templates/migration.rb +22 -0
- data/generators/delayed_job/templates/script +5 -0
- data/lib/delayed/backend/active_record.rb +93 -0
- data/lib/delayed/backend/base.rb +130 -0
- data/lib/delayed/backend/data_mapper.rb +125 -0
- data/lib/delayed/backend/mongo_mapper.rb +110 -0
- data/lib/delayed/command.rb +114 -0
- data/lib/delayed/message_sending.rb +53 -0
- data/lib/delayed/performable_method.rb +62 -0
- data/lib/delayed/railtie.rb +10 -0
- data/lib/delayed/recipes.rb +50 -0
- data/lib/delayed/tasks.rb +15 -0
- data/lib/delayed/worker.rb +178 -0
- data/lib/delayed_job.rb +14 -0
- data/rails/init.rb +5 -0
- data/recipes/delayed_job.rb +1 -0
- data/spec/backend/active_record_job_spec.rb +46 -0
- data/spec/backend/data_mapper_job_spec.rb +16 -0
- data/spec/backend/mongo_mapper_job_spec.rb +94 -0
- data/spec/backend/shared_backend_spec.rb +372 -0
- data/spec/delayed_method_spec.rb +46 -0
- data/spec/message_sending_spec.rb +89 -0
- data/spec/performable_method_spec.rb +53 -0
- data/spec/sample_jobs.rb +26 -0
- data/spec/setup/active_record.rb +34 -0
- data/spec/setup/data_mapper.rb +8 -0
- data/spec/setup/mongo_mapper.rb +17 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/story_spec.rb +17 -0
- data/spec/worker_spec.rb +237 -0
- data/tasks/jobs.rake +1 -0
- metadata +327 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'backend/shared_backend_spec'
|
3
|
+
require 'delayed/backend/data_mapper'
|
4
|
+
|
5
|
+
describe Delayed::Backend::DataMapper::Job do
|
6
|
+
before(:all) do
|
7
|
+
@backend = Delayed::Backend::DataMapper::Job
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
# reset database before each example is run
|
12
|
+
DataMapper.auto_migrate!
|
13
|
+
end
|
14
|
+
|
15
|
+
it_should_behave_like 'a backend'
|
16
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'backend/shared_backend_spec'
|
3
|
+
require 'delayed/backend/mongo_mapper'
|
4
|
+
|
5
|
+
describe Delayed::Backend::MongoMapper::Job do
|
6
|
+
before(:all) do
|
7
|
+
@backend = Delayed::Backend::MongoMapper::Job
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
MongoMapper.database.collections.each(&:remove)
|
12
|
+
end
|
13
|
+
|
14
|
+
it_should_behave_like 'a backend'
|
15
|
+
|
16
|
+
describe "indexes" do
|
17
|
+
it "should have combo index on priority and run_at" do
|
18
|
+
@backend.collection.index_information.detect { |index| index[0] == 'priority_1_run_at_1' }.should_not be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should have index on locked_by" do
|
22
|
+
@backend.collection.index_information.detect { |index| index[0] == 'locked_by_1' }.should_not be_nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "delayed method" do
|
27
|
+
class MongoStoryReader
|
28
|
+
def read(story)
|
29
|
+
"Epilog: #{story.tell}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class MongoStory
|
34
|
+
include ::MongoMapper::Document
|
35
|
+
key :text, String
|
36
|
+
|
37
|
+
def tell
|
38
|
+
text
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should ignore not found errors because they are permanent" do
|
43
|
+
story = MongoStory.create :text => 'Once upon a time...'
|
44
|
+
job = story.delay.tell
|
45
|
+
story.destroy
|
46
|
+
lambda { job.invoke_job }.should_not raise_error
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should store the object as string" do
|
50
|
+
story = MongoStory.create :text => 'Once upon a time...'
|
51
|
+
job = story.delay.tell
|
52
|
+
|
53
|
+
job.payload_object.class.should == Delayed::PerformableMethod
|
54
|
+
job.payload_object.object.should == story
|
55
|
+
job.payload_object.method.should == :tell
|
56
|
+
job.payload_object.args.should == []
|
57
|
+
job.payload_object.perform.should == 'Once upon a time...'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should store arguments as string" do
|
61
|
+
story = MongoStory.create :text => 'Once upon a time...'
|
62
|
+
job = MongoStoryReader.new.delay.read(story)
|
63
|
+
job.payload_object.class.should == Delayed::PerformableMethod
|
64
|
+
job.payload_object.method.should == :read
|
65
|
+
job.payload_object.args.should == [story]
|
66
|
+
job.payload_object.perform.should == 'Epilog: Once upon a time...'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "before_fork" do
|
71
|
+
after do
|
72
|
+
MongoMapper.connection.connect
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should disconnect" do
|
76
|
+
lambda do
|
77
|
+
Delayed::Backend::MongoMapper::Job.before_fork
|
78
|
+
end.should change { !!MongoMapper.connection.connected? }.from(true).to(false)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "after_fork" do
|
83
|
+
before do
|
84
|
+
MongoMapper.connection.close
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should call reconnect" do
|
88
|
+
lambda do
|
89
|
+
Delayed::Backend::MongoMapper::Job.after_fork
|
90
|
+
end.should change { !!MongoMapper.connection.connected? }.from(false).to(true)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,372 @@
|
|
1
|
+
shared_examples_for 'a backend' do
|
2
|
+
let(:worker) {Delayed::Worker.new }
|
3
|
+
|
4
|
+
def create_job(opts = {})
|
5
|
+
@backend.create(opts.merge(:payload_object => SimpleJob.new))
|
6
|
+
end
|
7
|
+
|
8
|
+
before do
|
9
|
+
Delayed::Worker.max_priority = nil
|
10
|
+
Delayed::Worker.min_priority = nil
|
11
|
+
Delayed::Worker.default_priority = 99
|
12
|
+
SimpleJob.runs = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should set run_at automatically if not set" do
|
16
|
+
@backend.create(:payload_object => ErrorJob.new ).run_at.should_not be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should not set run_at automatically if already set" do
|
20
|
+
later = @backend.db_time_now + 5.minutes
|
21
|
+
@backend.create(:payload_object => ErrorJob.new, :run_at => later).run_at.should be_close(later, 1)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise ArgumentError when handler doesn't respond_to :perform" do
|
25
|
+
lambda { @backend.enqueue(Object.new) }.should raise_error(ArgumentError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should increase count after enqueuing items" do
|
29
|
+
@backend.enqueue SimpleJob.new
|
30
|
+
@backend.count.should == 1
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should be able to set priority when enqueuing items" do
|
34
|
+
@job = @backend.enqueue SimpleJob.new, 5
|
35
|
+
@job.priority.should == 5
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should use default priority when it is not set" do
|
39
|
+
@job = @backend.enqueue SimpleJob.new
|
40
|
+
@job.priority.should == 99
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should be able to set run_at when enqueuing items" do
|
44
|
+
later = @backend.db_time_now + 5.minutes
|
45
|
+
@job = @backend.enqueue SimpleJob.new, 5, later
|
46
|
+
@job.run_at.should be_close(later, 1)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should work with jobs in modules" do
|
50
|
+
M::ModuleJob.runs = 0
|
51
|
+
job = @backend.enqueue M::ModuleJob.new
|
52
|
+
lambda { job.invoke_job }.should change { M::ModuleJob.runs }.from(0).to(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should raise an DeserializationError when the job class is totally unknown" do
|
56
|
+
job = @backend.new :handler => "--- !ruby/object:JobThatDoesNotExist {}"
|
57
|
+
lambda { job.payload_object.perform }.should raise_error(Delayed::Backend::DeserializationError)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should try to load the class when it is unknown at the time of the deserialization" do
|
61
|
+
job = @backend.new :handler => "--- !ruby/object:JobThatDoesNotExist {}"
|
62
|
+
job.should_receive(:attempt_to_load).with('JobThatDoesNotExist').and_return(true)
|
63
|
+
lambda { job.payload_object.perform }.should raise_error(Delayed::Backend::DeserializationError)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should try include the namespace when loading unknown objects" do
|
67
|
+
job = @backend.new :handler => "--- !ruby/object:Delayed::JobThatDoesNotExist {}"
|
68
|
+
job.should_receive(:attempt_to_load).with('Delayed::JobThatDoesNotExist').and_return(true)
|
69
|
+
lambda { job.payload_object.perform }.should raise_error(Delayed::Backend::DeserializationError)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should also try to load structs when they are unknown (raises TypeError)" do
|
73
|
+
job = @backend.new :handler => "--- !ruby/struct:JobThatDoesNotExist {}"
|
74
|
+
job.should_receive(:attempt_to_load).with('JobThatDoesNotExist').and_return(true)
|
75
|
+
lambda { job.payload_object.perform }.should raise_error(Delayed::Backend::DeserializationError)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should try include the namespace when loading unknown structs" do
|
79
|
+
job = @backend.new :handler => "--- !ruby/struct:Delayed::JobThatDoesNotExist {}"
|
80
|
+
job.should_receive(:attempt_to_load).with('Delayed::JobThatDoesNotExist').and_return(true)
|
81
|
+
lambda { job.payload_object.perform }.should raise_error(Delayed::Backend::DeserializationError)
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "find_available" do
|
85
|
+
it "should not find failed jobs" do
|
86
|
+
@job = create_job :attempts => 50, :failed_at => @backend.db_time_now
|
87
|
+
@backend.find_available('worker', 5, 1.second).should_not include(@job)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should not find jobs scheduled for the future" do
|
91
|
+
@job = create_job :run_at => (@backend.db_time_now + 1.minute)
|
92
|
+
@backend.find_available('worker', 5, 4.hours).should_not include(@job)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should not find jobs locked by another worker" do
|
96
|
+
@job = create_job(:locked_by => 'other_worker', :locked_at => @backend.db_time_now - 1.minute)
|
97
|
+
@backend.find_available('worker', 5, 4.hours).should_not include(@job)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should find open jobs" do
|
101
|
+
@job = create_job
|
102
|
+
@backend.find_available('worker', 5, 4.hours).should include(@job)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should find expired jobs" do
|
106
|
+
@job = create_job(:locked_by => 'worker', :locked_at => @backend.db_time_now - 2.minutes)
|
107
|
+
@backend.find_available('worker', 5, 1.minute).should include(@job)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should find own jobs" do
|
111
|
+
@job = create_job(:locked_by => 'worker', :locked_at => (@backend.db_time_now - 1.minutes))
|
112
|
+
@backend.find_available('worker', 5, 4.hours).should include(@job)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should find only the right amount of jobs" do
|
116
|
+
10.times { create_job }
|
117
|
+
@backend.find_available('worker', 7, 4.hours).should have(7).jobs
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when another worker is already performing an task, it" do
|
122
|
+
|
123
|
+
before :each do
|
124
|
+
@job = @backend.create :payload_object => SimpleJob.new, :locked_by => 'worker1', :locked_at => @backend.db_time_now - 5.minutes
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should not allow a second worker to get exclusive access" do
|
128
|
+
@job.lock_exclusively!(4.hours, 'worker2').should == false
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should allow a second worker to get exclusive access if the timeout has passed" do
|
132
|
+
@job.lock_exclusively!(1.minute, 'worker2').should == true
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should be able to get access to the task if it was started more then max_age ago" do
|
136
|
+
@job.locked_at = 5.hours.ago
|
137
|
+
@job.save
|
138
|
+
|
139
|
+
@job.lock_exclusively! 4.hours, 'worker2'
|
140
|
+
@job.reload
|
141
|
+
@job.locked_by.should == 'worker2'
|
142
|
+
@job.locked_at.should > 1.minute.ago
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should not be found by another worker" do
|
146
|
+
@backend.find_available('worker2', 1, 6.minutes).length.should == 0
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should be found by another worker if the time has expired" do
|
150
|
+
@backend.find_available('worker2', 1, 4.minutes).length.should == 1
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should be able to get exclusive access again when the worker name is the same" do
|
154
|
+
@job.lock_exclusively!(5.minutes, 'worker1').should be_true
|
155
|
+
@job.lock_exclusively!(5.minutes, 'worker1').should be_true
|
156
|
+
@job.lock_exclusively!(5.minutes, 'worker1').should be_true
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "when another worker has worked on a task since the job was found to be available, it" do
|
161
|
+
|
162
|
+
before :each do
|
163
|
+
@job = @backend.create :payload_object => SimpleJob.new
|
164
|
+
@job_copy_for_worker_2 = @backend.find(@job.id)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should not allow a second worker to get exclusive access if already successfully processed by worker1" do
|
168
|
+
@job.destroy
|
169
|
+
@job_copy_for_worker_2.lock_exclusively!(4.hours, 'worker2').should == false
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should not allow a second worker to get exclusive access if failed to be processed by worker1 and run_at time is now in future (due to backing off behaviour)" do
|
173
|
+
@job.update_attributes(:attempts => 1, :run_at => 1.day.from_now)
|
174
|
+
@job_copy_for_worker_2.lock_exclusively!(4.hours, 'worker2').should == false
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "reserve" do
|
179
|
+
before do
|
180
|
+
Delayed::Worker.max_run_time = 2.minutes
|
181
|
+
@worker = Delayed::Worker.new(:quiet => true)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should not reserve failed jobs" do
|
185
|
+
create_job :attempts => 50, :failed_at => described_class.db_time_now
|
186
|
+
described_class.reserve(@worker).should be_nil
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should not reserve jobs scheduled for the future" do
|
190
|
+
create_job :run_at => (described_class.db_time_now + 1.minute)
|
191
|
+
described_class.reserve(@worker).should be_nil
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should lock the job so other workers can't reserve it" do
|
195
|
+
job = create_job
|
196
|
+
described_class.reserve(@worker).should == job
|
197
|
+
new_worker = Delayed::Worker.new(:quiet => true)
|
198
|
+
new_worker.name = 'worker2'
|
199
|
+
described_class.reserve(new_worker).should be_nil
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should reserve open jobs" do
|
203
|
+
job = create_job
|
204
|
+
described_class.reserve(@worker).should == job
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should reserve expired jobs" do
|
208
|
+
job = create_job(:locked_by => @worker.name, :locked_at => described_class.db_time_now - 3.minutes)
|
209
|
+
described_class.reserve(@worker).should == job
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should reserve own jobs" do
|
213
|
+
job = create_job(:locked_by => @worker.name, :locked_at => (described_class.db_time_now - 1.minutes))
|
214
|
+
described_class.reserve(@worker).should == job
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context "#name" do
|
219
|
+
it "should be the class name of the job that was enqueued" do
|
220
|
+
@backend.create(:payload_object => ErrorJob.new ).name.should == 'ErrorJob'
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should be the method that will be called if its a performable method object" do
|
224
|
+
@job = Story.delay.create
|
225
|
+
@job.name.should == "Story.create"
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should be the instance method that will be called if its a performable method object" do
|
229
|
+
@job = Story.create(:text => "...").delay.save
|
230
|
+
@job.name.should == 'Story#save'
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "worker prioritization" do
|
235
|
+
before(:each) do
|
236
|
+
Delayed::Worker.max_priority = nil
|
237
|
+
Delayed::Worker.min_priority = nil
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should fetch jobs ordered by priority" do
|
241
|
+
10.times { @backend.enqueue SimpleJob.new, rand(10) }
|
242
|
+
jobs = @backend.find_available('worker', 10)
|
243
|
+
jobs.size.should == 10
|
244
|
+
jobs.each_cons(2) do |a, b|
|
245
|
+
a.priority.should <= b.priority
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should only find jobs greater than or equal to min priority" do
|
250
|
+
min = 5
|
251
|
+
Delayed::Worker.min_priority = min
|
252
|
+
10.times {|i| @backend.enqueue SimpleJob.new, i }
|
253
|
+
jobs = @backend.find_available('worker', 10)
|
254
|
+
jobs.each {|job| job.priority.should >= min}
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should only find jobs less than or equal to max priority" do
|
258
|
+
max = 5
|
259
|
+
Delayed::Worker.max_priority = max
|
260
|
+
10.times {|i| @backend.enqueue SimpleJob.new, i }
|
261
|
+
jobs = @backend.find_available('worker', 10)
|
262
|
+
jobs.each {|job| job.priority.should <= max}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
context "clear_locks!" do
|
267
|
+
before do
|
268
|
+
@job = create_job(:locked_by => 'worker', :locked_at => @backend.db_time_now)
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should clear locks for the given worker" do
|
272
|
+
@backend.clear_locks!('worker')
|
273
|
+
@backend.find_available('worker2', 5, 1.minute).should include(@job)
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should not clear locks for other workers" do
|
277
|
+
@backend.clear_locks!('worker1')
|
278
|
+
@backend.find_available('worker1', 5, 1.minute).should_not include(@job)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context "unlock" do
|
283
|
+
before do
|
284
|
+
@job = create_job(:locked_by => 'worker', :locked_at => @backend.db_time_now)
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should clear locks" do
|
288
|
+
@job.unlock
|
289
|
+
@job.locked_by.should be_nil
|
290
|
+
@job.locked_at.should be_nil
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context "large handler" do
|
295
|
+
before do
|
296
|
+
text = "Lorem ipsum dolor sit amet. " * 1000
|
297
|
+
@job = @backend.enqueue Delayed::PerformableMethod.new(text, :length, {})
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should have an id" do
|
301
|
+
@job.id.should_not be_nil
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
context "named queues" do
|
306
|
+
context "when worker has one queue set" do
|
307
|
+
before(:each) do
|
308
|
+
worker.queues = ['large']
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should only work off jobs which are from its queue" do
|
312
|
+
SimpleJob.runs.should == 0
|
313
|
+
|
314
|
+
create_job(:queue => "large")
|
315
|
+
create_job(:queue => "small")
|
316
|
+
worker.work_off
|
317
|
+
|
318
|
+
SimpleJob.runs.should == 1
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
context "when worker has two queue set" do
|
323
|
+
before(:each) do
|
324
|
+
worker.queues = ['large', 'small']
|
325
|
+
end
|
326
|
+
|
327
|
+
it "should only work off jobs which are from its queue" do
|
328
|
+
SimpleJob.runs.should == 0
|
329
|
+
|
330
|
+
create_job(:queue => "large")
|
331
|
+
create_job(:queue => "small")
|
332
|
+
create_job(:queue => "medium")
|
333
|
+
create_job
|
334
|
+
worker.work_off
|
335
|
+
|
336
|
+
SimpleJob.runs.should == 2
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
context "when worker does not have queue set" do
|
341
|
+
before(:each) do
|
342
|
+
worker.queues = []
|
343
|
+
end
|
344
|
+
|
345
|
+
it "should work off all jobs" do
|
346
|
+
SimpleJob.runs.should == 0
|
347
|
+
|
348
|
+
create_job(:queue => "one")
|
349
|
+
create_job(:queue => "two")
|
350
|
+
create_job
|
351
|
+
worker.work_off
|
352
|
+
|
353
|
+
SimpleJob.runs.should == 3
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
context "max_attempts" do
|
359
|
+
before(:each) do
|
360
|
+
@job = described_class.enqueue SimpleJob.new
|
361
|
+
end
|
362
|
+
|
363
|
+
it 'should not be defined' do
|
364
|
+
@job.max_attempts.should be_nil
|
365
|
+
end
|
366
|
+
|
367
|
+
it 'should use the max_retries value on the payload when defined' do
|
368
|
+
@job.payload_object.stub!(:max_attempts).and_return(99)
|
369
|
+
@job.max_attempts.should == 99
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|