Search code examples
ruby-on-railsrubydelayed-job

How to allow delayed function to be delayed in Rails test environment


I have a Rails model class with a function to be executed at a later time, which is managed by Delayed::Job. Here is the function (simplified):

def fn_with_dj_delay
  puts "puts output here"
  do_somethting_else  
end
handle_asynchronously :fn_with_dj_delay, :run_at => Proc.new { 24.hours.from_now }, :queue => 'my_queue'

When the function is called in my Rails test environment however, the delaying is being skipped. Is it possible for this to perform the same in both environments?

In rails c test the function fires immediately. Here is a slightly simplified and truncated console log:

2.3.1 :004 > x = MyClass.new
2.3.1 :005 > x.save!
2.3.1 :006 > x.fn_with_dj_delay
puts output here
 => #<Delayed::Backend::ActiveRecord::Job id: nil, priority: 0, attempts: 0 # ...
2.3.1 :007 > Delayed::Job.last
  Delayed::Backend::ActiveRecord::Job Load (0.3ms)  SELECT  `delayed_jobs`.*  # ...
 => nil

In rails c the function is automatically delayed as instructed. Again, a slightly simplified and truncated console log:

2.3.1 :004 > x = MyClass.new
2.3.1 :005 > x.save!
2.3.1 :006 > x.fn_with_dj_delay
   (0.2ms)  BEGIN
  SQL (0.4ms)  INSERT INTO `delayed_jobs` (`handler`, `run_at`, # ...
   (0.5ms)  COMMIT
 => true
2.3.1 :007 > Delayed::Job.last
    Delayed::Backend::ActiveRecord::Job Load (2.2ms)  SELECT  `delayed_jobs`.* # ...
 => #<Delayed::Backend::ActiveRecord::Job id: 1, priority: 0, attempts: 0 # ...

The only clue I can see is the returned, uninstantiated Delayed::Backend::ActiveRecord::Job object in the test console when the function finishes. If there is something invalid about the object, I could understand this failure, though I would expect an error to be raised. Regardless, this is not at issue:

2.3.1 :004 > res = p.check_for_similar_web_data
puts output here
 => #<Delayed::Backend::ActiveRecord::Job id: nil, priority: 0, attempts: 0 # ...
2.3.1 :005 > res.valid?
 => true
2.3.1 :006 > res.save!
   (0.1ms)  BEGIN
  SQL (0.4ms)  INSERT INTO `delayed_jobs` (`handler`, `run_at` # ...
   (0.5ms)  COMMIT
 => true

Solution

  • This is so simple, I'm surprised and embarrassed I didn't find it before writing this up. I guess the default is false in the test environment?

    2.3.1 :003 > Delayed::Worker.delay_jobs = true
    2.3.1 :004 > x = MyClass.new
    2.3.1 :005 > x.save!
    2.3.1 :006 > x.fn_with_dj_delay
       (0.2ms)  BEGIN
      SQL (0.4ms)  INSERT INTO `delayed_jobs` (`handler`, `run_at`, # ...
       (0.5ms)  COMMIT
     => true
    2.3.1 :007 > Delayed::Job.last
        Delayed::Backend::ActiveRecord::Job Load (2.2ms)  SELECT  `delayed_jobs`.* # ...
     => #<Delayed::Backend::ActiveRecord::Job id: 1, priority: 0, attempts: 0 # ..
    

    As seen (in reverse) here.