Skip to content
Newer
Older
100644 273 lines (204 sloc) 9.24 KB
75b49dc @tobi Initial extraction
authored
1 require File.dirname(__FILE__) + '/database'
2
3 class SimpleJob
0581928 @technoweenie remove excess whitespace
technoweenie authored
4 cattr_accessor :runs; self.runs = 0
75b49dc @tobi Initial extraction
authored
5 def perform; @@runs += 1; end
0581928 @technoweenie remove excess whitespace
technoweenie authored
6 end
75b49dc @tobi Initial extraction
authored
7
8 class ErrorJob
0581928 @technoweenie remove excess whitespace
technoweenie authored
9 cattr_accessor :runs; self.runs = 0
10 def perform; raise 'did not work'; end
75b49dc @tobi Initial extraction
authored
11 end
12
13 describe Delayed::Job do
249c5a9 @tobi Added min/max priority levels for workers. This allows you to have de…
authored
14 before do
15 Delayed::Job.max_priority = nil
16 Delayed::Job.min_priority = nil
17
18 Delayed::Job.delete_all
19 end
20
21 before(:each) do
22 SimpleJob.runs = 0
23 end
75b49dc @tobi Initial extraction
authored
24
41552cf @mocoso Added support to Delayed::Job#enqueue for setting jobs to run after a…
mocoso authored
25 it "should set run_at automatically if not set" do
b9dc92b @tobi Don't save jobs with empty handlers
authored
26 Delayed::Job.create(:payload_object => ErrorJob.new ).run_at.should_not == nil
0581928 @technoweenie remove excess whitespace
technoweenie authored
27 end
75b49dc @tobi Initial extraction
authored
28
41552cf @mocoso Added support to Delayed::Job#enqueue for setting jobs to run after a…
mocoso authored
29 it "should not set run_at automatically if already set" do
30 later = 5.minutes.from_now
31 Delayed::Job.create(:payload_object => ErrorJob.new, :run_at => later).run_at.should == later
32 end
33
75b49dc @tobi Initial extraction
authored
34 it "should raise ArgumentError when handler doesn't respond_to :perform" do
35 lambda { Delayed::Job.enqueue(Object.new) }.should raise_error(ArgumentError)
36 end
0581928 @technoweenie remove excess whitespace
technoweenie authored
37
75b49dc @tobi Initial extraction
authored
38 it "should increase count after enqueuing items" do
0581928 @technoweenie remove excess whitespace
technoweenie authored
39 Delayed::Job.enqueue SimpleJob.new
75b49dc @tobi Initial extraction
authored
40 Delayed::Job.count.should == 1
41 end
0581928 @technoweenie remove excess whitespace
technoweenie authored
42
41552cf @mocoso Added support to Delayed::Job#enqueue for setting jobs to run after a…
mocoso authored
43 it "should be able to set priority when enqueuing items" do
44 Delayed::Job.enqueue SimpleJob.new, 5
45 Delayed::Job.first.priority.should == 5
46 end
47
48 it "should be able to set run_at when enqueuing items" do
49 later = 5.minutes.from_now
50 Delayed::Job.enqueue SimpleJob.new, 5, later
51
52 # use be close rather than equal to because millisecond values cn be lost in DB round trip
53 Delayed::Job.first.run_at.should be_close(later, 1)
54 end
55
0581928 @technoweenie remove excess whitespace
technoweenie authored
56 it "should call perform on jobs when running work_off" do
75b49dc @tobi Initial extraction
authored
57 SimpleJob.runs.should == 0
0581928 @technoweenie remove excess whitespace
technoweenie authored
58
59 Delayed::Job.enqueue SimpleJob.new
8ec934e @tobi Removed the global lock. Jobs can now processed in parallel by runnin…
authored
60 Delayed::Job.work_off
0581928 @technoweenie remove excess whitespace
technoweenie authored
61
62 SimpleJob.runs.should == 1
63 end
a137def @defunkt Changes extracted from GitHub:
defunkt authored
64
65 it "should re-schedule by about 1 second at first and increment this more and more minutes when it fails to execute properly" do
0581928 @technoweenie remove excess whitespace
technoweenie authored
66 Delayed::Job.enqueue ErrorJob.new
0c084e5 @technoweenie merge
technoweenie authored
67 Delayed::Job.work_off(1)
8ec934e @tobi Removed the global lock. Jobs can now processed in parallel by runnin…
authored
68
75b49dc @tobi Initial extraction
authored
69 job = Delayed::Job.find(:first)
a137def @defunkt Changes extracted from GitHub:
defunkt authored
70
71 job.last_error.should =~ /did not work/
72 job.last_error.should =~ /job_spec.rb:10:in `perform'/
75b49dc @tobi Initial extraction
authored
73 job.attempts.should == 1
0c084e5 @technoweenie merge
technoweenie authored
74
75 job.run_at.should > Delayed::Job.db_time_now - 10.minutes
76 job.run_at.should < Delayed::Job.db_time_now + 10.minutes
0581928 @technoweenie remove excess whitespace
technoweenie authored
77 end
78
75b49dc @tobi Initial extraction
authored
79 it "should raise an DeserializationError when the job class is totally unknown" do
80
a137def @defunkt Changes extracted from GitHub:
defunkt authored
81 job = Delayed::Job.new
75b49dc @tobi Initial extraction
authored
82 job['handler'] = "--- !ruby/object:JobThatDoesNotExist {}"
83
0581928 @technoweenie remove excess whitespace
technoweenie authored
84 lambda { job.payload_object.perform }.should raise_error(Delayed::DeserializationError)
75b49dc @tobi Initial extraction
authored
85 end
86
87 it "should try to load the class when it is unknown at the time of the deserialization" do
0581928 @technoweenie remove excess whitespace
technoweenie authored
88 job = Delayed::Job.new
75b49dc @tobi Initial extraction
authored
89 job['handler'] = "--- !ruby/object:JobThatDoesNotExist {}"
90
91 job.should_receive(:attempt_to_load).with('JobThatDoesNotExist').and_return(true)
0581928 @technoweenie remove excess whitespace
technoweenie authored
92
93 lambda { job.payload_object.perform }.should raise_error(Delayed::DeserializationError)
94 end
95
75b49dc @tobi Initial extraction
authored
96 it "should try include the namespace when loading unknown objects" do
0581928 @technoweenie remove excess whitespace
technoweenie authored
97 job = Delayed::Job.new
75b49dc @tobi Initial extraction
authored
98 job['handler'] = "--- !ruby/object:Delayed::JobThatDoesNotExist {}"
0581928 @technoweenie remove excess whitespace
technoweenie authored
99 job.should_receive(:attempt_to_load).with('Delayed::JobThatDoesNotExist').and_return(true)
100 lambda { job.payload_object.perform }.should raise_error(Delayed::DeserializationError)
101 end
102
75b49dc @tobi Initial extraction
authored
103 it "should also try to load structs when they are unknown (raises TypeError)" do
0581928 @technoweenie remove excess whitespace
technoweenie authored
104 job = Delayed::Job.new
75b49dc @tobi Initial extraction
authored
105 job['handler'] = "--- !ruby/struct:JobThatDoesNotExist {}"
106
107 job.should_receive(:attempt_to_load).with('JobThatDoesNotExist').and_return(true)
0581928 @technoweenie remove excess whitespace
technoweenie authored
108
109 lambda { job.payload_object.perform }.should raise_error(Delayed::DeserializationError)
110 end
111
75b49dc @tobi Initial extraction
authored
112 it "should try include the namespace when loading unknown structs" do
0581928 @technoweenie remove excess whitespace
technoweenie authored
113 job = Delayed::Job.new
75b49dc @tobi Initial extraction
authored
114 job['handler'] = "--- !ruby/struct:Delayed::JobThatDoesNotExist {}"
0c084e5 @technoweenie merge
technoweenie authored
115
0581928 @technoweenie remove excess whitespace
technoweenie authored
116 job.should_receive(:attempt_to_load).with('Delayed::JobThatDoesNotExist').and_return(true)
117 lambda { job.payload_object.perform }.should raise_error(Delayed::DeserializationError)
a137def @defunkt Changes extracted from GitHub:
defunkt authored
118 end
41552cf @mocoso Added support to Delayed::Job#enqueue for setting jobs to run after a…
mocoso authored
119
a693dc9 @defunkt test both sides of destroy_jobs behavior
defunkt authored
120 it "should be failed if it failed more than MAX_ATTEMPTS times and we don't want to destroy jobs" do
757f585 @defunkt add documentation and rename destroy_jobs to the more descriptive des…
defunkt authored
121 default = Delayed::Job.destroy_failed_jobs
122 Delayed::Job.destroy_failed_jobs = false
b53ac48 @defunkt whether or not jobs should be destroyed is now configurable (old jobs…
defunkt authored
123
a6e374e @tobi Fixed a nasty bug that allowed several job runners to get the exclusi…
authored
124 @job = Delayed::Job.create :payload_object => SimpleJob.new, :attempts => 50
b53ac48 @defunkt whether or not jobs should be destroyed is now configurable (old jobs…
defunkt authored
125 @job.reload.failed_at.should == nil
0c084e5 @technoweenie merge
technoweenie authored
126 @job.reschedule 'FAIL'
b53ac48 @defunkt whether or not jobs should be destroyed is now configurable (old jobs…
defunkt authored
127 @job.reload.failed_at.should_not == nil
128
757f585 @defunkt add documentation and rename destroy_jobs to the more descriptive des…
defunkt authored
129 Delayed::Job.destroy_failed_jobs = default
a137def @defunkt Changes extracted from GitHub:
defunkt authored
130 end
131
a693dc9 @defunkt test both sides of destroy_jobs behavior
defunkt authored
132 it "should be destroyed if it failed more than MAX_ATTEMPTS times and we want to destroy jobs" do
757f585 @defunkt add documentation and rename destroy_jobs to the more descriptive des…
defunkt authored
133 default = Delayed::Job.destroy_failed_jobs
134 Delayed::Job.destroy_failed_jobs = true
a6e374e @tobi Fixed a nasty bug that allowed several job runners to get the exclusi…
authored
135
136 @job = Delayed::Job.create :payload_object => SimpleJob.new, :attempts => 50
0c084e5 @technoweenie merge
technoweenie authored
137 @job.should_receive(:destroy)
138 @job.reschedule 'FAIL'
a693dc9 @defunkt test both sides of destroy_jobs behavior
defunkt authored
139
757f585 @defunkt add documentation and rename destroy_jobs to the more descriptive des…
defunkt authored
140 Delayed::Job.destroy_failed_jobs = default
a693dc9 @defunkt test both sides of destroy_jobs behavior
defunkt authored
141 end
142
a137def @defunkt Changes extracted from GitHub:
defunkt authored
143 it "should never find failed jobs" do
144 @job = Delayed::Job.create :payload_object => SimpleJob.new, :attempts => 50, :failed_at => Time.now
145 Delayed::Job.find_available(1).length.should == 0
0581928 @technoweenie remove excess whitespace
technoweenie authored
146 end
147
be23e26 @rares fixing spec that was returning a false positive. adding spec for conc…
rares authored
148 context "when another worker is already performing an task, it" do
0581928 @technoweenie remove excess whitespace
technoweenie authored
149
8ec934e @tobi Removed the global lock. Jobs can now processed in parallel by runnin…
authored
150 before :each do
151 Delayed::Job.worker_name = 'worker1'
a6e374e @tobi Fixed a nasty bug that allowed several job runners to get the exclusi…
authored
152 @job = Delayed::Job.create :payload_object => SimpleJob.new, :locked_by => 'worker1', :locked_at => Delayed::Job.db_time_now - 5.minutes
8ec934e @tobi Removed the global lock. Jobs can now processed in parallel by runnin…
authored
153 end
0581928 @technoweenie remove excess whitespace
technoweenie authored
154
155 it "should not allow a second worker to get exclusive access" do
156 lambda { @job.lock_exclusively! 4.hours, 'worker2' }.should raise_error(Delayed::Job::LockError)
be23e26 @rares fixing spec that was returning a false positive. adding spec for conc…
rares authored
157 end
a6e374e @tobi Fixed a nasty bug that allowed several job runners to get the exclusi…
authored
158
be23e26 @rares fixing spec that was returning a false positive. adding spec for conc…
rares authored
159 it "should allow a second worker to get exclusive access if the timeout has passed" do
160 lambda { @job.lock_exclusively! 1.minute, 'worker2' }.should_not raise_error(Delayed::Job::LockError)
a6e374e @tobi Fixed a nasty bug that allowed several job runners to get the exclusi…
authored
161 end
5998931 Renamed locked_until to locked_at. We now store when we start a given…
Tobias Lütke authored
162
0581928 @technoweenie remove excess whitespace
technoweenie authored
163 it "should be able to get access to the task if it was started more then max_age ago" do
5998931 Renamed locked_until to locked_at. We now store when we start a given…
Tobias Lütke authored
164 @job.locked_at = 5.hours.ago
165 @job.save
166
0581928 @technoweenie remove excess whitespace
technoweenie authored
167 @job.lock_exclusively! 4.hours, 'worker2'
5998931 Renamed locked_until to locked_at. We now store when we start a given…
Tobias Lütke authored
168 @job.reload
169 @job.locked_by.should == 'worker2'
170 @job.locked_at.should > 1.minute.ago
171 end
8ec934e @tobi Removed the global lock. Jobs can now processed in parallel by runnin…
authored
172
7274142 @eric Job#find_available does not return running jobs
eric authored
173 it "should not be found by another worker" do
174 Delayed::Job.worker_name = 'worker2'
75b49dc @tobi Initial extraction
authored
175
7274142 @eric Job#find_available does not return running jobs
eric authored
176 Delayed::Job.find_available(1, 6.minutes).length.should == 0
177 end
a137def @defunkt Changes extracted from GitHub:
defunkt authored
178
7274142 @eric Job#find_available does not return running jobs
eric authored
179 it "should be found by another worker if the time has expired" do
180 Delayed::Job.worker_name = 'worker2'
a137def @defunkt Changes extracted from GitHub:
defunkt authored
181
7274142 @eric Job#find_available does not return running jobs
eric authored
182 Delayed::Job.find_available(1, 4.minutes).length.should == 1
183 end
8ec934e @tobi Removed the global lock. Jobs can now processed in parallel by runnin…
authored
184
a137def @defunkt Changes extracted from GitHub:
defunkt authored
185 it "should be able to get exclusive access again when the worker name is the same" do
a6e374e @tobi Fixed a nasty bug that allowed several job runners to get the exclusi…
authored
186 @job.lock_exclusively! 5.minutes, 'worker1'
0c084e5 @technoweenie merge
technoweenie authored
187 @job.lock_exclusively! 5.minutes, 'worker1'
188 @job.lock_exclusively! 5.minutes, 'worker1'
8ec934e @tobi Removed the global lock. Jobs can now processed in parallel by runnin…
authored
189 end
916e9f2 @tobi Slightly more useful Job#name method that can easily be used for insp…
authored
190 end
191
192 context "#name" do
193 it "should be the class name of the job that was enqueued" do
194 Delayed::Job.create(:payload_object => ErrorJob.new ).name.should == 'ErrorJob'
195 end
196
197 it "should be the method that will be called if its a performable method object" do
198 Delayed::Job.send_later(:clear_locks!)
199 Delayed::Job.last.name.should == 'CLASS:Delayed::Job#clear_locks!'
200 end
201 end
249c5a9 @tobi Added min/max priority levels for workers. This allows you to have de…
authored
202
203 context "worker prioritization" do
204
205 before(:each) do
206 Delayed::Job.max_priority = nil
207 Delayed::Job.min_priority = nil
208 end
209
210 it "should only work_off jobs that are >= min_priority" do
211 Delayed::Job.min_priority = -5
212 Delayed::Job.max_priority = 5
213 SimpleJob.runs.should == 0
214
215 Delayed::Job.enqueue SimpleJob.new, -10
216 Delayed::Job.enqueue SimpleJob.new, 0
217 Delayed::Job.work_off
218
219 SimpleJob.runs.should == 1
220 end
221
222 it "should only work_off jobs that are <= max_priority" do
223 Delayed::Job.min_priority = -5
224 Delayed::Job.max_priority = 5
225 SimpleJob.runs.should == 0
226
227 Delayed::Job.enqueue SimpleJob.new, 10
228 Delayed::Job.enqueue SimpleJob.new, 0
229
230 Delayed::Job.work_off
231
232 SimpleJob.runs.should == 1
233 end
234
8ec934e @tobi Removed the global lock. Jobs can now processed in parallel by runnin…
authored
235 end
249c5a9 @tobi Added min/max priority levels for workers. This allows you to have de…
authored
236
5855847 @rares removing worthless spec that duplicated a previous one.
rares authored
237 context "when pulling jobs off the queue for processing, it" do
4b9b079 @rares active record changes and fixing some small bugs.
rares authored
238 before(:each) do
5e8745c @rares more specs around poping jobs off the queue.
rares authored
239 @job = Delayed::Job.create(
240 :payload_object => SimpleJob.new,
241 :locked_by => 'worker1',
242 :locked_at => Delayed::Job.db_time_now - 5.minutes)
4b9b079 @rares active record changes and fixing some small bugs.
rares authored
243 end
be23e26 @rares fixing spec that was returning a false positive. adding spec for conc…
rares authored
244
5855847 @rares removing worthless spec that duplicated a previous one.
rares authored
245 it "should leave the queue in a consistent state and not run the job if locking fails" do
5e8745c @rares more specs around poping jobs off the queue.
rares authored
246 SimpleJob.runs.should == 0
247 @job.stub!(:lock_exclusively!).with(:any_args).once.and_raise(Delayed::Job::LockError)
149f45f @rares adding new un-finished specs
rares authored
248 Delayed::Job.should_receive(:find_available).once.and_return([@job])
5e8745c @rares more specs around poping jobs off the queue.
rares authored
249 Delayed::Job.work_off(1)
250 SimpleJob.runs.should == 0
4b9b079 @rares active record changes and fixing some small bugs.
rares authored
251 end
252
253 end
254
be23e26 @rares fixing spec that was returning a false positive. adding spec for conc…
rares authored
255 context "while running alongside other workers with enqueued jobs, it" do
149f45f @rares adding new un-finished specs
rares authored
256 before(:each) do
be23e26 @rares fixing spec that was returning a false positive. adding spec for conc…
rares authored
257 Delayed::Job.worker_name = 'worker1'
146642f @rares merging tobi/master in and fixing spec logic
rares authored
258 Delayed::Job.create(:payload_object => SimpleJob.new, :locked_by => 'worker1', :locked_at => (Delayed::Job.db_time_now - 3.minutes))
259 Delayed::Job.create(:payload_object => SimpleJob.new, :locked_by => 'worker2', :locked_at => (Delayed::Job.db_time_now - 11.minutes))
260 Delayed::Job.create(:payload_object => SimpleJob.new, :locked_by => 'worker1', :locked_at => (Delayed::Job.db_time_now - 2.minutes))
149f45f @rares adding new un-finished specs
rares authored
261 end
262
146642f @rares merging tobi/master in and fixing spec logic
rares authored
263 it "should only find jobs if the lock has expired reguardless of the worker" do
be23e26 @rares fixing spec that was returning a false positive. adding spec for conc…
rares authored
264 SimpleJob.runs.should == 0
146642f @rares merging tobi/master in and fixing spec logic
rares authored
265 Delayed::Job.work_off(5)
266 SimpleJob.runs.should == 2
267 Delayed::Job.find_available(5, 10.minutes).length.should == 1
149f45f @rares adding new un-finished specs
rares authored
268 end
269
270 end
271
a137def @defunkt Changes extracted from GitHub:
defunkt authored
272 end
Something went wrong with that request. Please try again.