Asynchronous Action Mailer [Rails 4 Countdown to 2013]

Posted on

This post is part of a series of 31 Rails 4 articles being released each day in December 2012.

The queue feature has been removed from the master branch, which means it will not be making the initial Rails 4.0 release.

Since Rails 4 has introduced a Queue into the framework, a primary candidate to take advantage of it was Action Mailer.

By default, Action Mailer will set all mailers inheriting from ActionMailer::Base to use ActiveSupport::SynchronousQueue. This provides Rails 3 developers the exact same interface they are used to, as all emails are delivered synchronously.

Configuration

Action Mailers are configured by default to use the application queue, Rails.queue. To enable asynchronous mailers, set queue in production.rb to a non-synchronous queue, such as ActiveSupport::Queue.new

# production.rb
config.queue = ActiveSupport::Queue.new

You can also use a different queue globally for all your mailers via the configuration option action_mailer.queue:

# production.rb
config.queue = ActiveSupport::Queue.new
config.action_mailer.queue = Sidekiq::Client::Queue.new

Finally, you are able to assign a queue to a specific mailer through the queue accessor:

class SubscriptionMailer < ActionMailer::Base
  self.queue = MailerQueue.new
  ...
end

Preparing your mailers for Queues

Queues such as Resque or Sidekiq, persist jobs as JSON objects. This means that if you are using one of these queues, you must ensure your mailer arguments can be marshalled to JSON.

For example, instead of passing an Active Record model to a mailer:

SubscriptionMailer.welcome(@user).deliver

You would pass an identifier:

SubscriptionMailer.welcome(@user.id).deliver

So that your mailer can query the database for the object:

class SubscriptionMailer < ActionMailer::Base
  def welcome(user_id)
    @user = User.find(user_id)
    mail(to: @user.email, subject: 'Thanks for subscribing!')
  end
end

There is also an added benefit of querying for records from queue jobs. It ensures you are working with the most up to date version of your model, eliminating the chance of stale data being used.

002

This post is by Kevin Faustino. Kevin is the Chief Craftsman of Remarkable Labs and also the founder of the Toronto Ruby Brigade.


Comments

comments powered by Disqus