Rails 4.2 Retrieves Delayed Job ID from Active Job

Any idea how to get the Delayed::Job ID from enqueuing ActiveJob? When I run the task, I return an instance of ActiveJob::Base with @job_id , but this job ID seems to be internal to ActiveJob. My best guess is to just go down the most recently created assignments:

 active_job_id = GenerateReportJob.perform_later(self.id).job_id delayed_job = Delayed::Job.order(id: :desc).limit(5).detect do |job| YAML.load(job.handler).job_data['job_id'] == active_job_id end 

but it looks like all kinds of hacks. The view is surprised that ActiveJob does not return an identifier from Delayed::Job , especially since this is what is explicitly returned when the job is in the queue.

== EDIT

Looks like I'm not the only one ( https://github.com/rails/rails/issues/18821 )

+6
source share
4 answers

In case someone finds this in the future: Rails has just accepted the patch so you can get this identifier from provider_job_id in Rails 5. You can make it work with a patch like

 ActiveJob::QueueAdapters::DelayedJobAdapter.singleton_class.prepend(Module.new do def enqueue(job) provider_job = super job.provider_job_id = provider_job.id provider_job end def enqueue_at(job, timestamp) provider_job = super job.provider_job_id = provider_job.id provider_job end end) 
+6
source

Inspired by Beguen's answer and some reverse engineering of the Rails 5 ActiveJob code, I made it work with Rails 4.2 on

1) adding the following code to lib/active_job/queue_adapters/delayed_job_adapter.rb or config/initializers/delayed_job.rb (both sites worked):

 # file: lib/active_job/queue_adapters/delayed_job_adapter.rb module ActiveJob module Core # ID optionally provided by adapter attr_accessor :provider_job_id end module QueueAdapters class DelayedJobAdapter class << self def enqueue(job) #:nodoc: delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name) job.provider_job_id = delayed_job.id delayed_job end def enqueue_at(job, timestamp) #:nodoc: delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp)) job.provider_job_id = delayed_job.id delayed_job end end class JobWrapper #:nodoc: attr_accessor :job_data def initialize(job_data) @job_data = job_data end def perform Base.execute(job_data) end end end end end 

The attr_accessor :provider_job_id statement is required in Rails 4.2 because it is used in the enqueue method and is not yet defined in 4.2.

Then we can use it as follows:

2) define our own ActiveJob class:

 # file: app/jobs/my_job.rb class MyJob < ActiveJob::Base queue_as :default def perform(object, performmethod = method(:method)) # Do something later returnvalue = object.send(performmethod) returnvalue end end end 

3) Now we can create a new task anywhere in the code:

 job = MyJob.perform_later(Myobject, "mymethod") 

This will Myobject.mymethod method.

4) The code in 1) helps to find the Delayed task related to our work:

 delayed_job = Delayed::Job.find(job.provider_job_id) 

5) finally, we can do whatever we do with the delay_job, for example. delete it:

 delayed_job.delete 

Note: in Rails 5, step 1) is no longer needed, since the same code is an integral part of Rails 5.

+3
source

I ran it in Rails 4.2 using the new Rails 5 patch as follows:

create the file lib/active_job/queue_adapters/delayed_job_adapter.rb

 module ActiveJob module QueueAdapters class DelayedJobAdapter class << self def enqueue(job) #:nodoc: delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name) job.provider_job_id = delayed_job.id delayed_job end def enqueue_at(job, timestamp) #:nodoc: delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp)) job.provider_job_id = delayed_job.id delayed_job end end class JobWrapper #:nodoc: attr_accessor :job_data def initialize(job_data) @job_data = job_data end def perform Base.execute(job_data) end end end end end 
+2
source

Instead of deleting a task from the queue if it is canceled, you can simulate the cancellation of the task itself.

Then, when you run GenerateReportJob , you can check the cancellation of the report first. If there is, then you can destroy the cancellation record and refuse to generate a report. If there is no cancellation, you can proceed as usual.

0
source

Source: https://habr.com/ru/post/985908/


All Articles