Home > Blockchain >  How to use Sorcery Gem with Sidekiq
How to use Sorcery Gem with Sidekiq

Time:01-15

I am using Sorcery Gem to Authenticate user in my Rails application. Everything is working fine. When user register then I am able to send user activation email. However sending email is taking long time so I was thinking to delay the email or send email in backgroud using Sidekiq. I read Sorcery documentation but couldn't find the way to delay the email using Sidekiq.

Please guide me how to delay the email send by Sorcery gem using Sidekiq.

CodePudding user response:

There could be two approach to this:

  1. Call Sidekiq worker inside Mailer
what I understand from the docs is that you can configure it to call any
Mailer. What you could do inside the method is call 
MailerJob.perform_late(*arg) instead of calling mail(*args) right away

Assuming you have a code something like this (ref: https://github.com/Sorcery/sorcery/wiki/User-Activation)

# app/mailers/user_mailer.rb
def activation_needed_email(user)
  @user = user
  @url  = activate_user_url(@user.activation_token)
  mail(to: user.email, subject: 'Welcome to My Awesome Site')
end

You can change the code to this

# app/mailers/user_mailer.rb
def activation_needed_email(user)
  @user = user
  @url  = activate_user_url(@user.activation_token)
  # mail(to: user.email, subject: 'Welcome to My Awesome Site')
  MyMailerWorker.perfor_later(to: user.email, subject: 'Welcome to My Awesome Site')
end

Your worker would be defined as per the sidekiq docs(ref: https://github.com/mperham/sidekiq/wiki/Getting-Started)

class MyMailerWorker
  include Sidekiq::Worker

  def perform(to: nil, subject: nil)
    MailerIWantToCall.send_activation_email(to, subject)
  end
end

P.S: Option 1 is not a clean approach but works if you are stuck with Sorcery legacy configs

  1. Don't set mail settings for srcoery(A cleaner approach)
Do not setup mail through sorcery at all.You can revert the changes 
mentioned for UserMailer on this page
(github.com/Sorcery/sorcery/wiki/User-Activation) and add a callback on User 
model based on when do you want to trigger an email and that way you have 
control over what to call and with sidekiq or not. 

CodePudding user response:

  1. Use snippet from DelayedJob Integration

     module Sorcery
       module Model
         module InstanceMethods
           def generic_send_email(method, mailer)
             config = sorcery_config
             mail = config.send(mailer).delay.send(config.send(method), self)
           end
         end
       end
     end
    

Add this code to bottom of the file: config/initializers/sorcery.rb.

  1. Add Sidekiq::Extensions.enable_delay! to config/initializers/sidekiq.rb.

  2. Add to config/environments/test.rb.

     config.active_job.queue_adapter = :sidekiq
     config.action_mailer.perform_deliveries = true
     config.action_mailer.raise_delivery_errors = true
     config.action_mailer.delivery_method = :test
     config.action_mailer.default_url_options = { :host => 'localhost:3000' }
    
  3. Example of method from UserMailer from User-Activation

     def activation_needed_email(user)
       @user = user
       @url  = activate_user_url(@user.activation_token)
       mail(to: user.email, subject: 'Activation')
     end
    
  4. Add to spec/rails_helper.rb.

     require 'sidekiq/testing'
     Sidekiq::Testing.fake!
    
  5. Write test to check it, must pass.

     require 'rails_helper'
    
     RSpec.describe UserMailer,
                    type: :mailer do
       let(:user) { create(:user) }
       let(:mail) { described_class.activation_needed_email(user) }
    
       describe 'activation_needed_email' do
         it 'creates job in sidekiq' do
           expect do
             mail
           end.to change { Sidekiq::Worker.jobs.size }.by(1)
         end
       end
     end
    
  •  Tags:  
  • Related