Handling Errors and Job Lifecycles in Rails 7.1: Master ActiveJob with `retry_on`, `discard_on`, and `after_discard`

Shah Zaib - Nov 5 - - Dev Community

Ruby on Rails 7.1 introduces some pivotal features to ActiveJob, streamlining error handling and job lifecycle management. In this post, I’ll walk you through how to effectively use after_discard, discard_on, and retry_on with examples to make your background job handling more robust.


1. after_discard Hook: Custom Actions for Discarded Jobs

Rails 7.1 introduces the after_discard callback, which lets you run custom logic when a job is discarded. It’s handy for logging errors, notifying administrators, or cleaning up resources.

Example:

class MyJob < ApplicationJob
  discard_on CustomError

  after_discard do |job|
    Rails.logger.info "Job #{job.job_id} was discarded."
    # You can add custom actions here, like sending notifications
  end

  def perform
    # Your job logic that might raise a CustomError
  end
end
Enter fullscreen mode Exit fullscreen mode

In this example, if CustomError occurs, the job gets discarded. The after_discard hook then logs the event and can trigger any additional custom behavior you need.


2. discard_on: Efficient Handling of Irrecoverable Errors

Use discard_on to specify exceptions that should result in discarding the job instead of retrying. This is crucial for errors you know cannot be fixed by retrying, like invalid data or a permanently missing record.

Example:

class ExampleJob < ApplicationJob
  discard_on ActiveRecord::RecordNotFound

  def perform(record_id)
    record = MyModel.find(record_id) # Raises an error if the record isn’t found
    # Perform your job logic on the record
  end
end
Enter fullscreen mode Exit fullscreen mode

When ActiveRecord::RecordNotFound is raised in this job, it is gracefully discarded without consuming additional resources or retries.


3. retry_on: Automatic Retries for Recoverable Errors

For errors that are likely temporary, retry_on provides a way to automatically retry jobs with configurable delays and limits. This is perfect for handling issues like network timeouts or transient service failures.

Example:

class RetryJob < ApplicationJob
  retry_on Net::OpenTimeout, wait: 5.seconds, attempts: 3

  def perform
    # Job logic that might encounter a temporary network issue
  end
end
Enter fullscreen mode Exit fullscreen mode

Here, if a Net::OpenTimeout error occurs, the job will retry up to three times with a 5-second pause between attempts, giving the external service a chance to recover.


Need a Rails Expert?

If you love what Rails can do and need a skilled full-stack developer to help you build robust, high-performance web applications, I'm available for new opportunities!

About Me: Shah Zaib

I’m a Full-Stack Developer and Technologist with 10+ years of experience delivering exceptional web projects. My expertise includes Ruby on Rails, Hotwire, and AI-powered solutions. From real-time app experiences to seamless AI integration, I’m passionate about transforming concepts into impactful software.

🌐 Connect with me on LinkedIn

Let’s discuss how I can help you innovate and elevate your next project!

. . . . . .
Terabox Video Player