Search code examples
ruby-on-railsrubydelayed-job

Adding validations to DelayedJob?


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?


Solution

  • 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.