Kiko Castro
Kiko Castro

Reputation: 632

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?

Upvotes: 4

Views: 1749

Answers (2)

hrdwdmrbl
hrdwdmrbl

Reputation: 5269

If you want to access the Delayed::Job from your worker, in an initializer, you can monkey patch the JobWrapper class.

module ActiveJob
  module QueueAdapters
    class DelayedJobAdapter
      class JobWrapper
        def perform(job)
        end
      end
    end
  end
end

Upvotes: 0

pthamm
pthamm

Reputation: 1841

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

Upvotes: 2

Related Questions