Search code examples
ruby-on-railsdelayed-jobrails-activejob

How to access Delayed Job instance inside Active Job - Rails 4.2


I'm using ActiveJob with delayed_job (4.0.6) in the background and I want to find a scheduled job to deleted it.

For instance, if I have

class MyClass

  def my_method
    perform_stuff
    MyJob.set(wait: 1.month.from_now).perform_later(current_user)
  end
end

Then, if I edit MyClass instance and call my_method again, I want to cancel that job and schedule a new one.

As suggested in this post http://www.sitepoint.com/delayed-jobs-best-practices, I added two columns to the Delayed Job Table:

table.integer :delayed_reference_id
table.string  :delayed_reference_type

add_index :delayed_jobs, [:delayed_reference_id],   :name => 'delayed_jobs_delayed_reference_id'
add_index :delayed_jobs, [:delayed_reference_type], :name => 'delayed_jobs_delayed_reference_type'

So this way I may find a delayed Job and destroy it. But I wanted to do that inside a ActiveJob class, to maintain the pattern of jobs in my project.

I wanted to do something like:

class MyJob < ActiveJob::Base

  after_enqueue do |job|
    user = self.arguments.first
    job.delayed_reference_id = user.id,
    job.delayed_reference_type = "User" 
  end

  def perform(user)
    delete_previous_job_if_exists(user_id)
  end

  def delete_previous_job_if_exists(user_id)
    Delayed::Job.find_by(delayed_reference_id: 1, delayed_reference_type: 'User').delete
  end
end

But that doesn't work.

Anyone had this kind of issue?


Solution

  • Two changes: 1. updated the after_enqueue callback so that you can update the delayed_jobs table directly 2. fixed a typo where delayed_reference_id was hard coded as 1

    This should work:

    class MyJob < ActiveJob::Base
    
      after_enqueue do |job|
        user = self.arguments.first
        delayed_job = Delayed::Job.find(job.provider_job_id)
        delayed_job.update(delayed_reference_id:user.id,delayed_reference_type:'User')
     end
    
      def perform(user)
        delete_previous_job_if_exists(user.id)
      end
    
      def delete_previous_job_if_exists(user_id)
        Delayed::Job.find_by(delayed_reference_id: user_id, delayed_reference_type: 'User').delete
      end
    end