37

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

4

4 回答 4

54

免责声明:我不是 delay_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"

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

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

于 2010-09-04T17:22:29.680 回答
7

delay_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
)
于 2013-09-27T14:31:57.570 回答
0

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

所以似乎对我有用的解决方案,避免手术,看起来像这样:

# 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 是一个 Delayed::Backend::ActiveRecord

:queue 字段就是任何字符串。我不认为它的价值在何时以及如何执行作业方面没有任何作用,除非您的代码对其进行了处理。

因此,我将我的应用程序逻辑与该 :queue 字段值挂钩,它适用于我的情况,根据要求:

  • 如果发出了新事件,则安排一个作业
  • 如果为此事件安排了任何相同的班级作业,则转储这些作业。
于 2020-06-08T20:34:10.240 回答
0

如果您仅通过其传递的参数查找作业,您也可以考虑使用延迟作业的 payload_object 方法。

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

于 2019-01-13T18:37:25.073 回答