Get Jazzed For ActiveJob!

What is ActiveJob?

Background Jobs have become a staple of web development in recent years. They enable us to avoid holding up the request/response flow while the application does something slow, like send emails, or make a ton of inserts that the user doesn’t really care about. In Rails development, we’ve had a myriad of options for queueing for a while now. We all know the popular ones: Resque, Sidekiq, Delayed Job, etc. Personally we’ve come to enjoy using Que because it gives us a simple API without adding dependencies to our applications (It’s backed by PostgreSQL, which we already use). Having the flexibility to weigh out pros and cons of a specific solution is really invaluable, but what happens when your needs change and you have to change your queueing infrastructure along with them? Turns out all the existing solutions are just different enough to cause pain when migrating between them. Fortunately, the Rails core team has heard our pleas for something better and in the upcoming Rails 4.2 release will bestow upon us the glory that is ActiveJob, a unified API for talking to Background job systems. As mentioned in Part 1 of our Rails 4.2 Overview, ActiveJob ships with adapters for several popular background job gems.

The Anatomy of a Job

Here is an extremely basic job definition:

class CoolJob < ActiveJob::Base
  queue_as :default

  def perform(options)
    thing = Thing.find(options[:thing_id])
    thing.do_stuff_or_whatever
  end
end

Pretty similar to what we’re used to with other systems. The queue name is set via queue_as (can be overridden at queue-time if desired) allowing you to set up separate queues that can be scaled independently of each other. Each Job will need to have perform defined. This method encapsulates the main logic that the Job will be responsible for running. ActiveJob also provides some additional optional configuration for handling lifecycle callbacks and exceptions.

Do Work.

OK, so you’ve defined your jobs. You have a few options for specifying when the job should run:

# queue up and execute as soon as worker is available
CoolJob.perform_later thing_id: 4
# queue up and wait a specified amount of time before sending
CoolJob.set(wait: 36.hours).perform_later thing_id: 17
# queue up a job to be executed at a specified time
SendReminder.set(wait_until: reminder.email_time).perform_later reminder_id: 1337

You can change some Job settings as you put it onto the queue:

# change which queue the job will be pushed onto
CoolJob.set(queue: :do_it_now).perform_later thing_id: 42

Lagniappe

Aside from providing a single API for all of (or at least most of) your Rails background job needs, ActiveJob has some other slightly hidden benefits. We’re really looking forward to an ActiveJob web interface that can be dropped into any Rails app. You can already use AciveJob::Stats to push ActiveJob metrics to statsd (and eventually other metrics platforms). Additionally, ActionMailer has received the ActiveJob treatment and has added #deliver_later, an ActionMailer method for automagically queuing emails, to all your Rails 4.2 mailers! (assuming, of course, you’ve got ActiveJob configured)