Methods
Instance Public methods
discard_on(exception)
Discard the job with no attempts to retry, if the exception is raised. This is useful when the subject of the job, like an Active Record, is no longer available, and the job is thus no longer relevant.
You can also pass a block that'll be invoked. This block is yielded with the job instance as the first and the error instance as the second parameter.
Example
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
📝 Source code
# File activejob/lib/active_job/exceptions.rb, line 79
def discard_on(exception)
rescue_from exception do |error|
if block_given?
yield self, error
else
logger.error "Discarded #{self.class} due to a #{exception}. The original exception was #{error.cause.inspect}."
end
end
end
🔎 See on GitHub
retry_on(exception, wait: 3.seconds, attempts: 5, queue: nil, priority: nil)
Catch the exception and reschedule job for re-execution after so many seconds, for a specific number of attempts. If the exception keeps getting raised beyond the specified number of attempts, the exception is allowed to bubble up to the underlying queuing system, which may have its own retry mechanism or place it in a holding queue for inspection.
You can also pass a block that'll be invoked if the retry attempts fail for custom logic rather than letting the exception bubble up. This block is yielded with the job instance as the first and the error instance as the second parameter.
Options
-
:wait
- Re-enqueues the job with a delay specified either in seconds (default: 3 seconds), as a computing proc that the number of executions so far as an argument, or as a symbol reference of:exponentially_longer
, which applies the wait algorithm of(executions ** 4) + 2
(first wait 3s, then 18s, then 83s, etc) -
:attempts
- Re-enqueues the job the specified number of times (default: 5 attempts) -
:queue
- Re-enqueues the job on a different queue -
:priority
- Re-enqueues the job with a different priority
Examples
class RemoteServiceJob < ActiveJob::Base
retry_on CustomAppException # defaults to 3s wait, 5 attempts
retry_on AnotherCustomAppException, wait: ->(executions) { executions * 2 }
retry_on(YetAnotherCustomAppException) do |job, error|
ExceptionNotifier.caught(error)
end
retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10
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 when the remote service is down
end
end
📝 Source code
# File activejob/lib/active_job/exceptions.rb, line 45
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, error
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
🔎 See on GitHub