How to cancel scheduled job with delayed_job in Rails?

Viewed 24748

I am scheduling a job to run in say, 10 minutes. How to properly cancel this particular job without using any kind of dirty extra fields in model and so on. Is there any call to remove particular job, or jobs related to specific model, instance, etc?

4 Answers

You may also consider using delayed job's payload_object method, if you're looking for a job through its passed parameter only.

Delayed::Job.all.each do |job|
  job.destroy if job_corresponds_to_target?(job, target)
end

def job_corresponds_to_target?(job, target)
  job.payload_object.args.first == target.id
end

This simplist example do not use fully the payload_object returned:

=> #<Delayed::PerformableMethod:0x0056551eae3660 @object=ReminderMailJob, @method_name=:perform_later, @args=[3]> 

I think it may get pricey to loop through all queued jobs serialized field (:handler), especially when queue is large (for example when rails eventstore replays events that you've subscribed to to schedule a job).

So the solution that seems to work for me, avoiding surgeries, looks like this:

# some_specific_event_handler.rb or policy 

record_uuid = SomeModel.find(event.data[:id]).uuid
queue_name = "#{record_uuid}_update_notification"
Delayed::Job.where(queue: queue_name).destroy_all
UpdateNotificationJob.set(
  wait: 30.minutes,
  queue: queue_name,
).perform_later(record_uuid)

Delayed::Job is a Delayed::Backend::ActiveRecord

The :queue field is just any string. I don't think its value plays any role in when and how job will be executed unless your code does something with it.

So I hooked my app logic to that :queue field value and it worked for my case, where, by requirements:

  • if new event was emitted then schedule a job
  • if there had been any same class jobs scheduled for this event, then dump those.
Related