如何在Rails中使用delayed_job取消预定作业?

时间:2010-09-03 17:48:34

标签: ruby-on-rails ruby ruby-on-rails-3 delayed-job

我安排一份工作,比如10分钟。如何在不使用模型中任何类型的脏字段的情况下正确取消此特定作业等。是否有任何要求删除特定工作或与特定模型,实例等相关的工作的电话?

4 个答案:

答案 0 :(得分:50)

免责声明:我不是delayed_job的专家用户......

是否有任何要求删除特定工作或与特定型号,实例等相关的工作的电话?

Delayed :: Job只是一个ActiveRecord对象,因此您可以查找并销毁其中的任何记录。根据您的使用情况,可以采用不同的方式处理。如果有人要手动销毁它们,可以通过Web应用程序中的管理界面来处理。

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

如果您需要按“作业类型”删除作业的某些流程外任务,您可以遍历每个作业,如果它与您的作业匹配则将其删除;在脚本/控制台中试试这个

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"

如果你想要删除MyJob类型的所有作业

,请给出上述内容
Delayed::Job.all.each do |job|
    if job.name == "MyJob" then
        job.delete
    end
end

这对您的情况可能有所帮助,也可能没有帮助?在许多情况下,您可能希望删除MyJob,但仅限于:some_value属性为'abc'而不是'xyz'。在这种情况下,您可能需要在MyJob对象上实现“display_name”。如果存在,job.name将使用它

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"

这样你可以更有选择性地删除哪些记录?

希望这能为您提供有关处理它的可能方法的足够信息吗?

答案 1 :(得分:7)

delayed_job 3引入了queue属性。这可以被劫持以安排可取消的工作。

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
)

答案 2 :(得分:0)

如果您仅通过传递的参数来查找作业,则还可以考虑使用延迟作业的有效负载对象方法。

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

此简化列表示例未完全使用返回的payload_object:

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

答案 3 :(得分:0)

我认为遍历所有排队的作业序列化字段(:handler)可能会很昂贵,尤其是在队列较大时(例如,在rails eventstore重播您已预订以安排作业的事件时)。

因此,对我来说似乎可行的避免手术的解决方案如下:

justify-content: space-evenly

Delayed :: Job是一个Delayed :: Backend :: ActiveRecord

:queue字段只是任何字符串。 我认为,除非您的代码对其执行了某些操作,否则它的值不会在何时以及如何执行作业中起作用。

因此,我将应用程序逻辑挂接到:queue字段值上,它适用于我的情况,在其中,根据要求:

  • 如果发出了新事件,则安排工作
  • 如果为此事件安排了任何同类的工作,则将其转储。