Skip to content

Commit b3cdd32

Browse files
committed
Merge remote-tracking branch 'raykrueger/better_failure_hooks'
2 parents cdd4a93 + 21ecfea commit b3cdd32

File tree

5 files changed

+52
-11
lines changed

5 files changed

+52
-11
lines changed

docs/HOOKS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ The available hooks are:
8686
`Resque::Failure` backend.
8787

8888
* `on_failure`: Called with the exception and job args if any exception occurs
89-
while performing the job (or hooks).
89+
while performing the job (or hooks), this includes Resque::DirtyExit.
9090

9191
Hooks are easily implemented with superclasses or modules. A superclass could
9292
look something like this.

lib/resque.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,19 +222,24 @@ def watch_queue(queue)
222222
#
223223
# If no queue can be inferred this method will raise a `Resque::NoQueueError`
224224
#
225+
# Returns true if the job was queued, nil if the job was rejected by a
226+
# before_enqueue hook.
227+
#
225228
# This method is considered part of the `stable` API.
226229
def enqueue(klass, *args)
227230
# Perform before_enqueue hooks. Don't perform enqueue if any hook returns false
228231
before_hooks = Plugin.before_enqueue_hooks(klass).collect do |hook|
229232
klass.send(hook, *args)
230233
end
231-
return if before_hooks.any? { |result| result == false }
234+
return nil if before_hooks.any? { |result| result == false }
232235

233236
Job.create(queue_from_class(klass), klass, *args)
234237

235238
Plugin.after_enqueue_hooks(klass).each do |hook|
236239
klass.send(hook, *args)
237240
end
241+
242+
return true
238243
end
239244

240245
# This method can be used to conveniently remove a job from a queue.

lib/resque/job.rb

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,6 @@ def perform
106106
job_args = args || []
107107
job_was_performed = false
108108

109-
before_hooks = Plugin.before_hooks(job)
110-
around_hooks = Plugin.around_hooks(job)
111-
after_hooks = Plugin.after_hooks(job)
112-
failure_hooks = Plugin.failure_hooks(job)
113-
114109
begin
115110
# Execute before_perform hook. Abort the job gracefully if
116111
# Resque::DontPerform is raised.
@@ -158,7 +153,7 @@ def perform
158153
# If an exception occurs during the job execution, look for an
159154
# on_failure hook then re-raise.
160155
rescue Object => e
161-
failure_hooks.each { |hook| job.send(hook, e, *job_args) }
156+
run_failure_hooks(e)
162157
raise e
163158
end
164159
end
@@ -176,6 +171,7 @@ def args
176171
# Given an exception object, hands off the needed parameters to
177172
# the Failure module.
178173
def fail(exception)
174+
run_failure_hooks(exception)
179175
Failure.create \
180176
:payload => payload,
181177
:exception => exception,
@@ -201,5 +197,27 @@ def ==(other)
201197
payload_class == other.payload_class &&
202198
args == other.args
203199
end
200+
201+
def before_hooks
202+
@before_hooks ||= Plugin.before_hooks(payload_class)
203+
end
204+
205+
def around_hooks
206+
@around_hooks ||= Plugin.around_hooks(payload_class)
207+
end
208+
209+
def after_hooks
210+
@after_hooks ||= Plugin.after_hooks(payload_class)
211+
end
212+
213+
def failure_hooks
214+
@failure_hooks ||= Plugin.failure_hooks(payload_class)
215+
end
216+
217+
def run_failure_hooks(exception)
218+
job_args = args || []
219+
failure_hooks.each { |hook| payload_class.send(hook, exception, *job_args) }
220+
end
221+
204222
end
205223
end

test/job_hooks_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,15 +277,15 @@ def self.perform(history)
277277
test "the before enqueue hook should run" do
278278
history = []
279279
@worker = Resque::Worker.new(:jobs)
280-
Resque.enqueue(BeforeEnqueueJob, history)
280+
assert Resque.enqueue(BeforeEnqueueJob, history)
281281
@worker.work(0)
282282
assert_equal history, [:before_enqueue], "before_enqueue was not run"
283283
end
284284

285285
test "a before enqueue hook that returns false should prevent the job from getting queued" do
286286
history = []
287287
@worker = Resque::Worker.new(:jobs)
288-
Resque.enqueue(BeforeEnqueueJobAbort, history)
288+
assert_nil Resque.enqueue(BeforeEnqueueJobAbort, history)
289289
assert_equal 0, Resque.size(:jobs)
290290
end
291291
end

test/worker_test.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,30 @@
3333
end
3434

3535
test "fails uncompleted jobs on exit" do
36-
job = Resque::Job.new(:jobs, [GoodJob, "blah"])
36+
job = Resque::Job.new(:jobs, {'class' => 'GoodJob', 'args' => "blah"})
3737
@worker.working_on(job)
3838
@worker.unregister_worker
3939
assert_equal 1, Resque::Failure.count
4040
end
4141

42+
class ::SimpleJobWithFailureHandling
43+
def self.on_failure_record_failure(exception)
44+
@@exception = exception
45+
end
46+
47+
def self.exception
48+
@@exception
49+
end
50+
end
51+
52+
test "fails uncompleted jobs on exit, and calls failure hook" do
53+
job = Resque::Job.new(:jobs, {'class' => 'SimpleJobWithFailureHandling', 'args' => ""})
54+
@worker.working_on(job)
55+
@worker.unregister_worker
56+
assert_equal 1, Resque::Failure.count
57+
assert(SimpleJobWithFailureHandling.exception.kind_of?(Resque::DirtyExit))
58+
end
59+
4260
test "can peek at failed jobs" do
4361
10.times { Resque::Job.create(:jobs, BadJob) }
4462
@worker.work(0)

0 commit comments

Comments
 (0)