Skip to content

Commit c8a3e0a

Browse files
committed
Merge pull request resque#398 from humancopy/resque
--- Before & after hooks for dequeue. Needed this to resolve deadlocks with resque-lock when dequeuing a job (see: humancopy/resque-lock@740f1ab). Thanks. ;)
2 parents 461351c + 17ad7f8 commit c8a3e0a

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

docs/HOOKS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ The available hooks are:
7272
* `after_enqueue`: Called with the job args after a job is placed on the queue.
7373
Any exception raised propagates up to the code which queued the job.
7474

75+
* `before_dequeue`: Called with the job args before a job is removed from the queue.
76+
If the hook returns `false`, the job will not be removed from the queue.
77+
78+
* `after_dequeue`: Called with the job args after a job was removed from the queue.
79+
Any exception raised propagates up to the code which dequeued the job.
80+
7581
* `before_perform`: Called with the job args before perform. If it raises
7682
`Resque::Job::DontPerform`, the job is aborted. If other exceptions
7783
are raised, they will be propagated up the the `Resque::Failure`

lib/resque.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,17 @@ def enqueue_to(queue, klass, *args)
283283
#
284284
# This method is considered part of the `stable` API.
285285
def dequeue(klass, *args)
286+
# Perform before_dequeue hooks. Don't perform dequeue if any hook returns false
287+
before_hooks = Plugin.before_dequeue_hooks(klass).collect do |hook|
288+
klass.send(hook, *args)
289+
end
290+
return if before_hooks.any? { |result| result == false }
291+
286292
Job.destroy(queue_from_class(klass), klass, *args)
293+
294+
Plugin.after_dequeue_hooks(klass).each do |hook|
295+
klass.send(hook, *args)
296+
end
287297
end
288298

289299
# Given a class, try to extrapolate an appropriate queue based on a

lib/resque/plugin.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,15 @@ def after_enqueue_hooks(job)
5252
def before_enqueue_hooks(job)
5353
job.methods.grep(/^before_enqueue/).sort
5454
end
55+
56+
# Given an object, returns a list `after_dequeue` hook names.
57+
def after_dequeue_hooks(job)
58+
job.methods.grep(/^after_dequeue/).sort
59+
end
60+
61+
# Given an object, returns a list `before_dequeue` hook names.
62+
def before_dequeue_hooks(job)
63+
job.methods.grep(/^before_dequeue/).sort
64+
end
5565
end
5666
end

test/job_hooks_test.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,66 @@ def self.perform(history)
290290
end
291291
end
292292

293+
context "Resque::Job after_dequeue" do
294+
include PerformJob
295+
296+
class ::AfterDequeueJob
297+
@queue = :jobs
298+
def self.after_dequeue_record_history(history)
299+
history << :after_dequeue
300+
end
301+
302+
def self.perform(history)
303+
end
304+
end
305+
306+
test "the after dequeue hook should run" do
307+
history = []
308+
@worker = Resque::Worker.new(:jobs)
309+
Resque.dequeue(AfterDequeueJob, history)
310+
@worker.work(0)
311+
assert_equal history, [:after_dequeue], "after_dequeue was not run"
312+
end
313+
end
314+
315+
316+
context "Resque::Job before_dequeue" do
317+
include PerformJob
318+
319+
class ::BeforeDequeueJob
320+
@queue = :jobs
321+
def self.before_dequeue_record_history(history)
322+
history << :before_dequeue
323+
end
324+
325+
def self.perform(history)
326+
end
327+
end
328+
329+
class ::BeforeDequeueJobAbort
330+
@queue = :jobs
331+
def self.before_dequeue_abort(history)
332+
false
333+
end
334+
335+
def self.perform(history)
336+
end
337+
end
338+
339+
test "the before dequeue hook should run" do
340+
history = []
341+
@worker = Resque::Worker.new(:jobs)
342+
Resque.dequeue(BeforeDequeueJob, history)
343+
@worker.work(0)
344+
assert_equal history, [:before_dequeue], "before_dequeue was not run"
345+
end
346+
347+
test "a before dequeue hook that returns false should prevent the job from getting dequeued" do
348+
history = []
349+
assert_equal nil, Resque.dequeue(BeforeDequeueJobAbort, history)
350+
end
351+
end
352+
293353
context "Resque::Job all hooks" do
294354
include PerformJob
295355

0 commit comments

Comments
 (0)