如果要创建ActiveJob并且perform块接受一个预期是ActiveRecord对象的单个实例的参数,那么当作业入队时,所讨论的对象存在,但是在实际执行时该对象不再存在,这项工作显然会失败,对吗?
MyJob < ActiveJob::Base
def perform(widget)
# do some stuff to widget
end
end
因此,一旦这项工作失败,因为ActiveJob无法实例化原始的ActiveRecord对象,它将继续失败。可以对作业进行哪些更新以停止故障循环。我考虑过挂钩before_perform
,但我还没有看到前进的道路。
除了解决手头的问题之外,我在这里学到的另一件事是传递widget_id
整数而不是ActiveRecord对象会更好。然后我就可以检查并查看有问题的小部件是否仍然存在于执行块内。
答案 0 :(得分:4)
当无法再找到某个对象时,您可以rescue_from
被抛出的ActiveJob::DeserializationError
。注意:这种反序列化在执行回调开始之前发生,这就是为什么你可以使用执行回调来处理这种情况。
因此,在您的工作班中,您可以添加:
class MyJob < ActiveJob::Base
rescue_from(ActiveJob::DeserializationError) do |exception|
# return true (we rescued) if the error causing the deserialization
# error was a record not being found
exception.original_exception == ActiveRecord::RecordNotFound
end
end
如果rescue_from
返回true
,则表示已处理错误并且作业已成功完成。在这种情况下,我刚刚检查了导致反序列化错误的错误是否为ActiveRecord::RecordNotFound
(这是ActiveJob用于序列化和反序列化ActiveRecord对象的globalid
gem导致无法找到宾语)。