If you have been using Ruby on Rails for a while now, you've probably run into the problem where a long process is taking a lot of time on the server locking it for any new request.
The solution is fairly easy by just sending that long process into a background job, and there are a lot of great gems out there to help us get the job done:
The issue here is that each one of them have their own DSL, which makes it hard to change between them if you don't encapsulate the logic into a class or set of classes.
Rails 4.2 integrates now an ActiveJob module which intention is to encapsulate a background job API. A list of available adapters can be found here http://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html
ActiveJob comes with a generator to help us create a file to handle a long process or set of long processes. For example, let's say we want send emails on a background process.
First we need to create the job to handle this:
$ rails g job emails
This should create a file under the
app/jobs directory, and may look like this:
class EmailsJob < ActiveJob::Base queue_as :default def perform(*args) # Do something later end end
And let's say that anytime a user signs up into our site, we want to deliver them a welcome email.
A simple implementation for that action would be like this:
class UsersController < ApplicationController def create @user = User.new(user_params) if @user.save UserMailer.welcome_email(user).deliver redirect_to @user, notice: 'Hey you just signed up, welcome!' else render :new end end end
EmailsJob class we just added, we can simply update the
welcome_email method on the controller like so:
And the implementation of the
perform method on the
EmailsJob class should look like this:
class EmailsJob < ActiveJob::Base queue_as :default def perform(*args) UserMailer.welcome_email(user).deliver end end
This way the welcome email will now be sent on background.
Sending emails seems like a must-have for every application(or at least on my experience) and Rails understands this, that's why it includes a
deliver_later method to achieve this:
Connect the backend
We have not talk about on how to set the driver or adapter to handle the background jobs processing.
The implementation is really simple, and it actually part of the
\#config/application.rb module YourApp class Application < Rails::Application # Be sure to have the adapter's gem in your Gemfile and follow # the adapter's specific installation and deployment instructions. config.active_job.queue_adapter = :delayed_job end end
In the example above we configured the adapter to use
delayed_job, but remember it can be
resque. For mor information on adapters head to http://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html
You have probably used background jobs in the past probably to send emails, process images, zip some documents and things can get messy really quick without the right implementation.
ActiveJob is this kind of implementation, take advantage of it, it will make your like much easier.