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= usermail(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_emailsThis 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 endendYou now need to install a queuing service to handle the background jobs. We have a variety of background queuing libraries such as delayed jobs, sidekiq, rescue, 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 installHowever, 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.
wait Enqueues the job with the specified delay wait_until Enqueues the job at the time specified queue Enqueues the job on the specified queue priority Enqueues 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:
Callback Description before_enqueue Defines a callback that will get called right before the job is enqueued. around_enqueue Defines a callback that will get called around the enqueuing of the job. after_enqueue Defines a callback that will get called right after the job is enqueued. before_perform Defines a callback that will get called right before the jobâs perform method is executed. around_perform Defines a callback that will get called around the jobâs perform method. after_perform Defines 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.
Leave a Reply