I'd like to add some restrictions to what jobs get added to my DelayedJob queue.
For example, when I do this:
Delayed::Job.enqueue Something.new(id)
I'd like have something similar to "validates_uniqueness" that stops more than one job for the same ID.
Any ideas how to organise such code?
Not sure where to do the validations. Especially seeing as my queue might have multiple different types of job classes?
The standard way of doing this is to push the validation out of the delayed job and into your application. That is: you allow the system to schedule multiple jobs, and your code ensures that it only runs once. The aasm gem might be useful to help you manage your state.
For instance, let's say you had a Person
model with name
and age
fields, and you wanted to fix up their name to be title case via delayed_job. Something like this:
class Person < ActiveRecord::Base
include AASM
aasm do
state :unprocessed, :initial => true
state :done
event :capitalize do
transitions :from => :unprocessed, :to => :done
end
end
def fix_name
self.name.split.each(&:capitalize!).join(' ') unless self.done?
self.capitalize
self.save
end
end
# Elsewhere in your code...
p = Person.new({name: "bob geldof"})
Delayed::Job.enqueue p.fix_name
We're using aasm to give our job two states: "unprocessed" and "done". The fix_name
code only runs if our model doesn't have the state 'done'. No matter how many times we enqueue a call to fix_name
, it'll only run once because our model can only move to the "done" state once.
Finally, if you know you're only ever going to have two states on your model (for instance, you don't need to differentiate pending/processing/done/failed) then using a boolean flag would be even simpler.