Sending asynchronous emails using Sidekiq on OpenShift
If you need to send transactional emails from your Rails application, you should always send them asynchronously using a background job. If you send transactional emails synchronously, the user will see a loading page for the time rails connect to SMTP server and delivers your email which is about 2-3 seconds. This will result in a very bad user experience and it’s advisable to send emails using a background job.
Sidekiq advertises it self as simple, efficient background processing engine for Ruby. Sidekiq has dependency on Redis version 2.4
or greater. Hence to setup Sidekiq on OpenShift, we have to setup Redis first. So let’s get started.
Setting up Redis
Redis cartridge for Openshift is available here. To add this cartridge to existing Openshift application, issue following command:
1
rhc add-cartridge http://cartreflect-claytondev.rhcloud.com/reflect?github=smarterclayton/openshift-redis-cart
If this command fails, inspect the log files generated at $OPENSHIFT_REDIS_DIR/logs/redis.log
.
Setting up Sidekiq
The Sidekiq community cartridge hasn’t been updated in a while and it doesn’t work with current OpenShift. Hence I forked the repository and fixed the issues. I also bumped the Sidekiq version to 3.3.1
which was latest at that time. You can see the code changes here.
To add Sidekiq cartridge to application, issue following command:
1
rhc add-cartridge http://cartreflect-claytondev.rhcloud.com/github/pranavpr/openshift-origin-cartridge-sidekiq --app myapp
Once the installation completes, you can access the monitoring interface at https://YOUR_APP-NAMESPACE.rhcloud.com/sidekiq
. Sidekiq will print the full URL with authentication after successful install.
Updating Gemfile
Add following line to your Gemfile
to add Sidekiq to your Rails application:
1
gem 'sidekiq'
Then do a bundle install
to finish installation of sidekiq
gem.
Send asynchronous emails using Sidekiq
Delayed extensions of Sidekiq allows sending emails asynchronously with Action Mailer out of the box. It provides three methods viz. delay
, delay_for(interval)
and delay_until(time)
, to send email asynchronously.
Use delay
to deliver emails asynchronously, delay_for(interval)
or delay_until(time)
to deliver the email at some point in the future.
1
2
3
UserMailer.delay.welcome_email(@user.id)
UserMailer.delay_for(5.days).find_more_friends_email(@user.id)
UserMailer.delay_until(5.days.from_now).find_more_friends_email(@user.id)
Devise emails
devise-async
gem provides the ability to send Devise emails using Sidekiq. Add following line to the Gemfile
:
1
gem 'devise-async'
And then execute bundle install
to finish installation of devise-async
gem.
Now add :async
to the devise call in your model:
1
2
3
class User < ActiveRecord::Base
devise :database_authenticatable, :async, :confirmable # etc ...
end
Finally set your queuing backend to Sidekiq by creating config/initializers/devise_async.rb
:
1
Devise::Async.backend = :sidekiq
Epilogue
I issued a pull request to merge my changes to community cartridge and it got accepted. So you can also use the community cartridge to add Sidekiq to your OpenShift application.