当您将对象传递给 ActiveJob 入队并且该对象在执行时不再存在时会发生什么?
What happens when you pass an object to an ActiveJob enqueue and that object no longer exists at perform time?
如果要创建一个 ActiveJob 并且执行块接受一个预期为 ActiveRecord 对象的单个实例的参数,那么当作业入队时,相关对象存在,但在实际执行时该对象不再存在,作业显然会失败,对吗?
MyJob < ActiveJob::Base
def perform(widget)
# do some stuff to widget
end
end
所以一旦这个job因为ActiveJob不能实例化原来的ActiveRecord对象而失败,它就会一直失败下去。可以对作业进行哪些更新以停止故障循环。我考虑挂钩 before_perform
,但我还没有看到前进的道路。
除了解决手头的问题,我在这里学到的另一件事是传递 widget_id
整数而不是 ActiveRecord 对象会更好。然后我就可以检查并查看有问题的小部件是否仍然存在于执行块中。
您可以 rescue_from
当无法再找到对象时抛出的 ActiveJob::DeserializationError
。注意:此反序列化发生在执行回调开始之前,这就是为什么您可以使用执行回调来处理这种情况。
因此,在您的工作中 class 您可以添加:
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
If rescue_from
returns true
表示错误已被处理并且作业已成功完成。在这种情况下,我刚刚检查了导致反序列化错误的错误是否是 ActiveRecord::RecordNotFound
(这是 ActiveJob 用于序列化和反序列化 ActiveRecord 对象的 globalid
gem 在找不到对象时导致的) .
如果要创建一个 ActiveJob 并且执行块接受一个预期为 ActiveRecord 对象的单个实例的参数,那么当作业入队时,相关对象存在,但在实际执行时该对象不再存在,作业显然会失败,对吗?
MyJob < ActiveJob::Base
def perform(widget)
# do some stuff to widget
end
end
所以一旦这个job因为ActiveJob不能实例化原来的ActiveRecord对象而失败,它就会一直失败下去。可以对作业进行哪些更新以停止故障循环。我考虑挂钩 before_perform
,但我还没有看到前进的道路。
除了解决手头的问题,我在这里学到的另一件事是传递 widget_id
整数而不是 ActiveRecord 对象会更好。然后我就可以检查并查看有问题的小部件是否仍然存在于执行块中。
您可以 rescue_from
当无法再找到对象时抛出的 ActiveJob::DeserializationError
。注意:此反序列化发生在执行回调开始之前,这就是为什么您可以使用执行回调来处理这种情况。
因此,在您的工作中 class 您可以添加:
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
If rescue_from
returns true
表示错误已被处理并且作业已成功完成。在这种情况下,我刚刚检查了导致反序列化错误的错误是否是 ActiveRecord::RecordNotFound
(这是 ActiveJob 用于序列化和反序列化 ActiveRecord 对象的 globalid
gem 在找不到对象时导致的) .