модуль ActiveJob::Exceptions::ClassMethods
Открытые методы экземпляров
# File activejob/lib/active_job/exceptions.rb, line 124 def after_discard(&blk) self.after_discard_procs += [blk] end
Блок кода, который выполняется, когда задача собирается быть отброшена по любой причине.
Пример
class WorkJob < ActiveJob::Base
after_discard do |job, exception|
ExceptionNotifier.report(exception)
end
...
end # File activejob/lib/active_job/exceptions.rb, line 103
def discard_on(*exceptions)
rescue_from(*exceptions) do |error|
instrument :discard, error: error do
yield self, error if block_given?
run_after_discard_procs(error)
end
end
end Отбросить задачу без попыток повторной обработки, если возникает исключение. Это полезно, когда предмет задачи, например, Active Record, больше недоступен, и задача, таким образом, больше не актуальна.
Также можно передать блок, который будет вызван. Этот блок получает в качестве параметров экземпляр задачи и экземпляр ошибки.
Обработчики retry_on и discard_on ищутся снизу вверх и по иерархии классов. Обработчик первого класса, для которого exception.is_a?(klass) выполняется, вызывается, если таковой имеется.
Пример
class SearchIndexingJob < ActiveJob::Base
discard_on ActiveJob::DeserializationError
discard_on(CustomAppException) do |job, error|
ExceptionNotifier.caught(error)
end
def perform(record)
# Will raise ActiveJob::DeserializationError if the record can't be deserialized
# Might raise CustomAppException for something domain specific
end
end
# File activejob/lib/active_job/exceptions.rb, line 62
def retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil, jitter: JITTER_DEFAULT)
rescue_from(*exceptions) do |error|
executions = executions_for(exceptions)
if attempts == :unlimited || executions < attempts
retry_job wait: determine_delay(seconds_or_duration_or_algorithm: wait, executions: executions, jitter: jitter), queue: queue, priority: priority, error: error
else
if block_given?
instrument :retry_stopped, error: error do
yield self, error
end
run_after_discard_procs(error)
else
instrument :retry_stopped, error: error
run_after_discard_procs(error)
raise error
end
end
end
end Перехватывает исключение и перепланирует задачу для повторного выполнения через заданное количество секунд, в определенное число попыток. Если исключение продолжает возникать после указанного количества попыток, исключение разрешается подняться до лежащей в основе системы очереди, которая может иметь собственный механизм повторной обработки или поместить его в очередь ожидания для проверки.
Также можно передать блок, который будет вызван, если попытки повторной обработки завершатся неудачей, для реализации пользовательской логики вместо того, чтобы допускать поднятие исключения. Этот блок получает в качестве параметров экземпляр задачи и экземпляр ошибки.
Обработчики retry_on и discard_on ищутся снизу вверх и по иерархии классов. Обработчик первого класса, для которого exception.is_a?(klass) выполняется, вызывается, если таковой имеется.
Параметры
-
:wait- Перезапускает задачу с задержкой, указанной в секундах (по умолчанию: 3 секунды), как вычисляемый proc, принимающий в качестве аргумента количество выполненных до этого запусков, или как символьное обозначение:polynomially_longer, которое применяет алгоритм ожидания((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2(первое ожидание ~3 секунды, затем ~18 секунд, затем ~83 секунды и т. д.) -
:attempts- Запускает задачу указанное количество раз (по умолчанию: 5 попыток) или как символьное обозначение:unlimitedдля повторной обработки задачи до тех пор, пока она не выполнится успешно. Количество попыток включает в себя исходное выполнение задачи. -
:queue- Перезапускает задачу в другой очереди -
:priority- Перезапускает задачу с другим приоритетом -
:jitter- Случайная задержка времени ожидания, используемая при расчете экспоненциальной задержки. По умолчанию составляет 15% (0.15), что представляет собой верхнюю границу возможного времени ожидания (выраженного в процентах)
Примеры
class RemoteServiceJob < ActiveJob::Base
retry_on CustomAppException # defaults to ~3s wait, 5 attempts
retry_on AnotherCustomAppException, wait: ->(executions) { executions * 2 }
retry_on CustomInfrastructureException, wait: 5.minutes, attempts: :unlimited
retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
retry_on Net::OpenTimeout, Timeout::Error, wait: :polynomially_longer, attempts: 10 # retries at most 10 times for Net::OpenTimeout and Timeout::Error combined
# To retry at most 10 times for each individual exception:
# retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 10
# retry_on Net::ReadTimeout, wait: 5.seconds, jitter: 0.30, attempts: 10
# retry_on Timeout::Error, wait: :polynomially_longer, attempts: 10
retry_on(YetAnotherCustomAppException) do |job, error|
ExceptionNotifier.caught(error)
end
def perform(*args)
# Might raise CustomAppException, AnotherCustomAppException, or YetAnotherCustomAppException for something domain specific
# Might raise ActiveRecord::Deadlocked when a local db deadlock is detected
# Might raise Net::OpenTimeout or Timeout::Error when the remote service is down
end
end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.