如果 ActiveJob 应该执行的对象被删除,我如何才能阻止它执行?

How can I prevent ActiveJob from performing if the object it should perform on is deleted?

我有一个后台作业可以处理上传的图片,但有时用户会在后台作业执行前删除图片,并创建一个 ActiveJob::DeserializationError

我可以在 before_destroy 的模型中做些什么来取消作业吗?或者在作业 class 中,我可以在 before_perform 中做些什么,以便在数据库中的记录已被删除时不执行作业?

谢谢!

处理作业中删除或未删除的记录class

begin
    record.reload
    # if no exception continue executing job
rescue ActiveRecord::RecordNotFound => e
    # If deleted exception is raised and skip executing the job
end

活动作业实例包括 ActiveSupport::Rescuable,这意味着您可以像在控制器中一样在作业中使用 rescue_from

然后您可以从任何反序列化错误中恢复:

class MyJob < ApplicationJob

  rescue_from(ActiveJob::DeserializationError) do |e|
    true 
  end

end

如果你想在很多工作中使用这个模式,你可以将它提取到一个模块中:

module DeserializationErrorIsOkay

  extend ActiveSupport::Concern

  included do
    rescue_from(ActiveJob::DeserializationError) do |e|
      # This error is okay and doesn't indicate a failed job
      true
    end
  end

end

您可以将其包括在您的工作中:

class MyJob < ApplicationJob
  include DeserializationErrorIsOkay
end

注意:这会从作业中序列化的任何对象中恢复,但无法反序列化

这可能是一个更新的答案:

discard_on ActiveJob::DeserializationError

参见:https://edgeguides.rubyonrails.org/active_job_basics.html#retrying-or-discarding-failed-jobs

示例:

class RemoteServiceJob < ApplicationJob
  retry_on CustomAppException # defaults to 3s wait, 5 attempts

  discard_on ActiveJob::DeserializationError

  def perform(*args)
    # Might raise CustomAppException or ActiveJob::DeserializationError
  end
end