How to cancel scheduled job with delayed_job in Rails?

痞子三分冷 提交于 2019-11-28 03:56:40

disclaimer: I am not an expert user of delayed_job...

"Is there any call to remove particular job, or jobs related to specific model, instance, etc?"

Delayed::Job is just an ActiveRecord object so you can find and destroy any of those records. Depending on your use case this could be handled different ways. If someone is going to manually destroy them this could be handled through an admin interface in your web app.

# list all jobs
Delayed::Job.all
# find a job by id
job = Delayed::Job.find(params[:id])
# delete it
job.delete

if you need some out of process task deleting jobs by 'job type' you could loop through each one and delete it if it matches your job; try this in script/console

class MyJob < Struct.new(:some_value);
    def perform
        # ...
    end
end

my_job = MyJob.new('xyz')
job = Delayed::Job.enqueue(my_job, 0, 1.hour.from_now)
job.name
# => "MyJob"
job.handler
# => "--- !ruby/struct:MyJob \nsome_value: xyz\n"

so given the above if you wanted to delete all jobs of type MyJob

Delayed::Job.all.each do |job|
    if job.name == "MyJob" then
        job.delete
    end
end

this may or may not help for your situation? in many cases you might want to delete a MyJob but only where the :some_value attribute was 'abc' and not 'xyz'. In this case you might need to implement a 'display_name' on your MyJob object. job.name will use this if it exists

class MyJob < Struct.new(:user_id);
    def perform
        # ...
    end

    def display_name
        return "MyJob-User-#{user_id}"
    end 
end

# store reference to a User
my_job = MyJob.new(User.first.id) # users.id is 1
job = Delayed::Job.enqueue(my_job, 0, 1.hour.from_now)
job.name
# => "MyJob-User-1"
job.handler
# => "--- !ruby/struct:MyJob \nuser_id: 1\n"

this way you could be more selective about which records to delete?

hopefully this gives you enough information on possible ways to handle it?

delayed_job 3 introduced a queue attribute. This can be hijacked to schedule a cancelable job.

class MyJob < Struct.new(:user_id)
  def self.queue_name
    "something-unique"
  end

  def perform
    # ...
  end
end

#scheduler
my_job = MyJob.new(User.first.id)
#'cancel' pending jobs first
Delayed::Job.where(queue: my_job.class.queue_name).destroy_all
#queue it up
Delayed::Job.enqueue(my_job,
  queue: my_job.class.queue_name,
  run_at: 1.hour.from_now
)

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]> 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!