Integrate Sneakers with Activejob

This guide provides you with all you need to get started in creating, enqueueing and executing background jobs with RabbitMQ and Sneakers in Active Job.

sneakers

Active Job and its integrations is on of the headline feature for Rails 4.2. Active Job is a framework for declaring jobs and making them run on a variety of queueing backends. We will in this guide show how to integrate ActiveJob with Sneakers. Sneakers is a high-performance background-job processing framework for Ruby based on RabbitMQ. We will be using the built in adapter for Sneakers as queueing backend.

After reading this guide, you will know:

  • How to set up Sneakers adapter for ActiveJob
  • How to create jobs
  • How to enqueue jobs with RabbitMQ as queueing backend
  • How to run jobs in the background
  • More about ActiveJob class basics

If you do not have access to RabbitMQ can you read about how to get started in the get started documentation. The documentation will show how to get started with a CloudAMQP managed RabbitMQ instance and how to download and setup a local RabbitMQ workstation. You can find more information about RabbitMQ here.

Install Sneakers

Install Sneakers by adding Sneakers to your application Gemfile

gem 'sneakers'
(execute by using bundle)

You can also install sneakers your self:
$ gem install sneakers

Install Active Job

If you are using Rails:
You will need Rails 4.2.0beta1 or greater if you want Active Job available by default (in older versions of Rails, you can require it as a gem). You need to install the latest version of 4.2 (at the time of the writing is it 4.2.0-beta2, edge Rails).

In the Gemfile of your app, change the version to

gem 'rails', '4.2.0.beta2'

(execute by using bundle)

If you are not using Rails:
In the Gemfile of your app, you need to add active job and active support with version greater then 4.2.0.beta2.

gem 'activesupport', '4.2.0.beta4'
gem 'activejob', '4.2.0.beta2'
(execute by using bundle)

Creating a Job

This section will provide a step-by-step guide to creating a job and enqueuing it. This code shows how to enqueue a Job, MyBackgroundJob , to be performed as soon as the queueing system is free to handle the job.

Start by require

require 'bundler/setup'
require 'active_job'
require 'sneakers'

You need to add the CLOUDAMQP_URL to the configuration for Sneaker. The URL can be found in the control panel for your instance. Use the username as the vhost.

opts = {
  :amqp => 'CLOUDAMQP_URL',
  :vhost => 'username',
  :exchange => 'sneakers',
  :exchange_type => :direct
}

Sneakers.configure(opts)

Queue adapter is specified by:

ActiveJob::Base.queue_adapter = :sneakers

There are two methods that are required by convention when creating an ActiveJob class. We have queue_as and perform .

Sneakers supports multiple queues. In the example is the MyBackgroundJob delegate to the queue job_queue by specifying the queue name using queue_as API. The perform method is the logic of the job handler, what you want to do with the job.
Note: If you are using arguments for this method, then it must be a legal JSON types such as String, Integer, Flat, nil, True/False, Hash, Array or GlobalID instances.

Sneakers.configure(opts)
ActiveJob::Base.queue_adapter = :sneakers

class MyBackgroundJob < ActiveJob::Base
  queue_as :job_queue

  def perform()
    puts 'Perform a job'
  end
end

# Enqueue a job to be performed as soon the queueing system is free.
MyBackgroundJob.perform_later()

Complete code

# activejob_with_sneakers.rb

require 'bundler/setup'
require 'active_job'
require 'sneakers'

opts = {
  :amqp => 'CLOUDAMQP_URL',
  :vhost => 'vhost',
  :exchange => 'sneakers',
  :exchange_type => :direct
}

Sneakers.configure(opts)
ActiveJob::Base.queue_adapter = :sneakers

class MyBackgroundJob < ActiveJob::Base
  queue_as :job_queue

  def perform()
    puts 'Perform a job'
  end
end

# Enqueue a job to be performed as soon the queueing system is free.
MyBackgroundJob.perform_later()

Run Sneakers

Run Sneakers with SneakersAdapter and required file. That could by done by entering following line into the console:

$ sneakers work ActiveJob::QueueAdapters::SneakersAdapter::JobWrapper --require activejob_with_sneakers.rb

This will give you an output that tells you that all the workers have started. Let sneakers run and open another console tab.

Now you need to run your application, activejob_with_sneakers.rb. MyBackgroundJob.perform_later() will add the job to the working queue.

$ ruby activejob_with_sneakers.rb

Following output will be listed in the console, telling that the job is added to the queue: job_queue with Sneakers as queueing adapter.

$ ruby activejob_with_sneakers.rb
[ActiveJobi] Enqueued MyBackgroundJob (Job ID: ca546f17...) to Sneakers(job_queue)
2014-11-04T09:00:58Z p-90523 t-ow6v6y7dw INFO: publishing
<{"job_class":"MyBackgroundJob","job_id":"ca546f17...","queue_name":"job_queue","arguments":[]}> to [job_queue]

If you now look in the other tab, you will see that the job is performed directly:

[ActiveJob] [MyBackgroundJob] [ca546f17...] Performing MyBackgroundJob from Sneakers(job_queue)
Perform a job
[ActiveJob] [MyBackgroundJob] [ca546f17...] Performed MyBackgroundJob from Sneakers(job_queue) in 0.03ms

If you want to can you open RabbitMQ admin console and go to the queue tab. You will see that the new queue: job_queue, is created and that the queue is beeing used.

Basic of ActiveJob class

Now we have seen the basic enqueuing with Active Job and Sneakers as queueing backend. We will now show some examples of how Active Job can be used by showing multiple jobs and Active Jobs Callbacks.

Prioritise with multi-queues

With Active Job you can schedule the job to run on a specific queue.

MyBackgroundJob.perform_later('input')
#Performing MyBackgroundJob from Sneakers(job_queue_2) with arguments: "input"
class MyBackgroundJob < ActiveJob::Base
  queue_as do
    if other_job_queue?
      :job_queue_2
    else
      :job_queue
    end
    #....

    def other_job_queue?
      # define if the job should have another queue
    end

    def perform(input)
      puts 'Perform a job'
    end

  end
end

Callbacks

Active Job provides hooks during the lifecycle of a job. Callbacks allow you to trigger logic during the lifecycle of a job. We can for example use callbacks to do job logging and to give notifications.

Callback functions:

  • before_enqueue
  • around_enqueue
  • after_enqueue
  • before_perform
  • around_perform
  • after_perform

class MyBackgroundJob < ActiveJob::Base
  queue_as :job_queue

  before_enqueue do |job|
    puts "Before job is enqueued"
  end

  before_perform do |job|
    puts "Before job is performed"
  end

  def perform(input)
    puts 'Perform a job'
  end
end

MyBackgroundJob.perform_later('input')

The code from above will give following output

[ActiveJob] Enqueued MyBackgroundJob (Job ID: 2303bad1) to Sneakers(other_job_queue) with arguments: "input"
Before job is enqueued
[ActiveJob] [MyBackgroundJob] [2303bad1] Performing MyBackgroundJob from Sneakers(job_queue) with arguments: "input"
Before job is performed
Perform a job
[ActiveJob] [MyBackgroundJob] [2303bad1] Performed MyBackgroundJob from Sneakers(job_queue) in 0.05ms

Feedback or questions

If you have any questions, comments or need feedback, please do not hesitate to contact us at support@cloudamqp.com .

CloudAMQP - industry leading RabbitMQ as a service

Start your managed cluster today. CloudAMQP is 100% free to try.

13,000+ users including these smart companies