module ActiveJob::Exceptions::ClassMethods
def discard_on(exception)
end
# Will raise ActiveJob::DeserializationError if the record can't be deserialized
def perform(record)
discard_on ActiveJob::DeserializationError
class SearchIndexingJob < ActiveJob::Base
==== Example
like an Active Record, is no longer available, and the job is thus no longer relevant.
Discard the job with no attempts to retry, if the exception is raised. This is useful when the subject of the job,
def discard_on(exception) rescue_from exception do |error| logger.error "Discarded #{self.class} due to a #{exception}. The original exception was #{error.cause.inspect}." end end
def retry_on(exception, wait: 3.seconds, attempts: 5, queue: nil, priority: nil)
end
# Might raise Net::OpenTimeout when the remote service is down
# Might raise ActiveRecord::Deadlocked when a local db deadlock is detected
# Might raise CustomAppException, AnotherCustomAppException, or YetAnotherCustomAppException for something domain specific
def perform(*args)
retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10
retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
end
ExceptionNotifier.caught(exception)
retry_on(YetAnotherCustomAppException) do |job, exception|
retry_on AnotherCustomAppException, wait: ->(executions) { executions * 2 }
retry_on CustomAppException # defaults to 3s wait, 5 attempts
class RemoteServiceJob < ActiveJob::Base
==== Examples
* :priority - Re-enqueues the job with a different priority
* :queue - Re-enqueues the job on a different queue
* :attempts - Re-enqueues the job the specified number of times (default: 5 attempts)
(first wait 3s, then 18s, then 83s, etc)
:exponentially_longer, which applies the wait algorithm of (executions ** 4) + 2
as a computing proc that the number of executions so far as an argument, or as a symbol reference of
* :wait - Re-enqueues the job with a delay specified either in seconds (default: 3 seconds),
==== Options
the exception bubble up. This block is yielded with the job instance as the first and the error instance as the second parameter.
You can also pass a block that'll be invoked if the retry attempts fail for custom logic rather than letting
holding queue for inspection.
bubble up to the underlying queuing system, which may have its own retry mechanism or place it in a
If the exception keeps getting raised beyond the specified number of attempts, the exception is allowed to
Catch the exception and reschedule job for re-execution after so many seconds, for a specific number of attempts.
def retry_on(exception, wait: 3.seconds, attempts: 5, queue: nil, priority: nil) rescue_from exception do |error| if executions < attempts logger.error "Retrying #{self.class} in #{wait} seconds, due to a #{exception}. The original exception was #{error.cause.inspect}." retry_job wait: determine_delay(wait), queue: queue, priority: priority else if block_given? yield self, exception else logger.error "Stopped retrying #{self.class} due to a #{exception}, which reoccurred on #{executions} attempts. The original exception was #{error.cause.inspect}." raise error end end end end