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.
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. Learn more about RabbitMQ
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 being 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 .