Active Job

The Active Job framework in Rails is extremely helpful for declaring background jobs and executing them asynchronously.

Applications that involve background tasks such as sending emails, pushing notifications, background processing of CSV files and backing up the databases, integration with external apps through APIs, handling file uploads, etc., can be scheduled with Active Job framework.

Emails with Active Job

As explained in the previous chapter (Ruby on Rails – Sending Emails), there is a welcome_email() method in the UserMailer class.

classUserMailer<ApplicationMailer
  default from:" GMAIL_USERNAME"defwelcome_email(user)@user= user
mail(to:@user.email, subject:"Welcome to My Awesome Site!")endend</pre>

Next, you need to create an Active Job with the following command:

rails generate job send_emails

This creates a custom job (SendEmailsJob) to handle the email-sending process asynchronously.

Active Job provides a default perform() method which you need to override to call the welcome_email() method from the UserMailer class.

classSendEmailsJob<ApplicationJob
  queue_as :defaultdefperform(user)UserMailer.welcome_email(user).deliver
  endend

You now need to install a queuing service to handle the background jobs. We have a variety of background queuing libraries such as delayed jobssidekiqrescue, and so on.

We will be using Sidekiq for the active job. For that, we must add a gem of sidekiq into Gemfile:

gem 'sidekiq'
bundle install

However, you need to let Rails know that this gem is to be used for background processing. So, edit your application.rb to set the active_job.queue_adapter.

moduleMyApplicationclassApplication<Rails::Application# make sure the adapter's gem has been included in your Gemfile.
config.active_job.queue_adapter =:sidekiqendend</pre>

Enqueuing the job

After configuring queueing backend, you must add your job to the queue. Enqueue a job for execution when the queuing system is available. Along with it, the queue will change whenever the time changes. You may set times for when a task needs to be completed after a month or to be executed as soon as possible.

Considering that SendEmailsJob is the name of our job, the multiple techniques listed below can be used to achieve enqueuing options.

waitEnqueues the job with the specified delay
wait_untilEnqueues the job at the time specified
queueEnqueues the job on the specified queue
priorityEnqueues the job with the specified priority

For example,

SendEmailsJob.set(wait:1.week).perform_later(user)

This statement schedules sending the email 1 week from now. Or,

SendEmailsJob.set(wait_until:Date.tomorrow.noon).perform_later(user)

Will start the job tomorrow at noon.

Recent versions of Ruby on Rails do not require you to generate a custom job when you're just using ActionMailer with deliver_later. To enable Active Job in your Rails application for sending emails asynchronously (such as when a User is created), you just need to queue the email delivery job instead of sending it directly.

Edit your UserController and modify the create action as below:

defcreate@user=User.new(user_params)[email protected]
  # UserMailer.welcome_email(@user).deliver_now  # Send email after user creationUserMailer.welcome_email(@user).deliver_later  # Send email later
  redirect_to @user, notice:"User was successfully created. A welcome email has been sent."else
  render :new, status::unprocessable_entityendend</pre>

You can specify the wait parameter to deliver_later() method such as −

UserMailer.welcome_email(user).deliver_later(wait:10.minutes)

Or,

UserMailer.welcome_email(user).deliver_later(wait_until:Time.tomorrow.noon)

Callbacks

The Active Job framework has certain hooks so that a defined logic can be triggered at various points during a job’s life cycle. These are the available callbacks for active jobs:

CallbackDescription
before_enqueueDefines a callback that will get called right before the job is enqueued.
around_enqueueDefines a callback that will get called around the enqueuing of the job.
after_enqueueDefines a callback that will get called right after the job is enqueued.
before_performDefines a callback that will get called right before the job’s perform method is executed.
around_performDefines a callback that will get called around the job’s perform method.
after_performDefines a callback that will get called right after the job’s perform method has finished.

Retrying or Discarding Failed Jobs

It's possible to retry or discard a failed job by using retry_on or discard_on, respectively. If the configuration doesn't specify, a failed job will not be retried. Using retry_on or discard_on, respectively, you can attempt again after a failed job. And default retry_on is to 3 seconds and 5 attempts.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *