codedecoder

breaking into the unknown…

sending email through background job using sidekiq

2 Comments

Hope you all are familiar with writing code to send a email in Rails, If not get the basic here . Many a time we need to send thousands of email to different user and it is better to handle them in background. We will use sidekiq to handle our background job. See here how to install and configure sidekiq . You can find a sample background job for making API calls , using sidekiq in this post .

O.k…so assuming, sidekiq is up in your application and it is allready triggering email successfully, you can push it to background with few simple step.

The flow will be like this :
=> You push the email delivery to background by using sidekiq delay method

say below is the line which trigger welcome email in the normal case

UserMailer.welcome_email(user_info).deliver #this will deliver the mail

to push it to background we will modify it to

UserMailer.delay.welcome_email(user_info) #this will deliver the mail in the background

=> We will keep checking the status of each email after say 1 second and on the basis of its status i,e failed or complete we will take further action like redirecting the user to next page or resending the email etc. below is the method which will do this for us.

  def check_email_status(job_id)
    job_status = "pending"
    elapsed_time = 0
    until (job_status == "complete" || job_status == "failed" || elapsed_time > 30) do
      job_status = Sidekiq::Status::status(job_id).to_s
      sleep SLEEP_BEFORE_CHECKING_BG_STATUS
      elapsed_time = elapsed_time + SLEEP_BEFORE_CHECKING_BG_STATUS
    end
    job_status
  end

Basically, these are the only change which you need to introduce in order to trigger a email in background.

I will just show you the line from this email post which needs to be modified to push the job in the background. Below is the changed code of UsersController

class UsersController < ApplicationController

  SLEEP_BEFORE_CHECKING_BG_STATUS = 1 #set the intervel after which status need to be cheked

  include Sidekiq::Worker # include sidekiq worker
  include Sidekiq::Status::Worker # include the status worker

  def new
    @user = User.new()
  end

  def create
    @user = User.new()
    @user = params[:user]
    if @user.save
      user_info = {:mail => @user.email, :username => @user.username,
      :temp_password => @user.temp_password }
      job_id = UserMailer.delay.welcome_email(user_info)  # will push the job to background and return id of that job
      email_status = check_email_status(job_id) # will keep checking the job after time set above
      if (email_status.to_s == “complete”) #depending on final action we are flashing the message
        flash[:notice] = “User created and email send”
      else
        flash[:notice] = “User created but email failed to send”
      end
    else
     render new
     flash[:notice] = “User failed to create”
    end
  end

 def check_email_status(job_id)
    job_status = “pending”
    elapsed_time = 0
    until (job_status == “complete” || job_status == “failed” || elapsed_time > 30) do
      job_status = Sidekiq::Status::status(job_id).to_s
      sleep SLEEP_BEFORE_CHECKING_BG_STATUS
      elapsed_time = elapsed_time + SLEEP_BEFORE_CHECKING_BG_STATUS
    end
    job_status
  end

end

So that’s all you need to do in order to handle email in the background

Reference :

https://github.com/mperham/sidekiq/wiki/Delayed-Extensions

Author: arunyadav4u

over 7 years experience in web development with Ruby on Rails.Involved in all stage of development lifecycle : requirement gathering, planing, coding, deployment & Knowledge transfer. I can adept to any situation, mixup very easily with people & can be a great friend.

2 thoughts on “sending email through background job using sidekiq

  1. Why use sidekiq if controller code is still synchronous? It kinda makes no sense.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s