#Rails Background Workers

Background Workers

Background workers are separate processes that can run along side a Rails server.

The rails server can send seperate jobs to the background workers that they can do to provide a fast experience for your users.

You can also schedule these jobs to run at a later time, for example say you want to archive posts after 30 days.

A common example is sending a welcome email, you wouldnt want the user to have to wait for your server to send an email before the page redirects them after they sign up, instead you would send that task to a worker. Take 5minutes and think up some use cases for background workers

Luckily, heroku just changed its pricing scheme and now lets us have a worker for free, and thats what we’re going to do today.

###Install Redis,

We’re going to be using a task worker called sidekiq, its the industry standard and incredibly powerful. It uses redis a database to store its tasks. To install redis, $ brew isntall redis and read the instructions it gives you and follow them. Check that redis is working with $ redis-cli ping

###Starter code clone the starter repo off of github here https://github.com/RobAWilkinson/backgroundjobs-STARTER-code

###Set up Sidekiq

we need to add the sidekiq gem into our gemfile and then bundle install. we need to tell rails to use sidekiq for ActiveJob

# config/application.rb
module SidekiqApp
  class Application < Rails::Application
    config.active_job.queue_adapter = :sidekiq
  end
end

Now I want you to open up a seperate tab and run bundle exec sidekiq inside your rails directory. if it says that it is ready to accept jobs, you’re in the clear.

we need a few more gems to make this work on heroku though so go ahead and add these gems in include redis, sidekiq, rails_12factor, thin and geocoder gem

bundle install

and run $ rails generate geocoder:config.

Now that we have the geocoder gem in there, we can open up our rails console and do something like this

Geocoder.search("91770")

Thsi returns a result object that you can pull latitude, longitude, city and state from. ###Making a worker

Now that we’ve got that working we’re going to convert that process to something that a worker does so we dont have to worry about long reload times.

We’re going to do this using rails 4.2 active jobs, like most things in rails it comes with a generator

rails g job geolocate_account

Now this will generate a job with a #perform method, make it so this method takes an Account does a Geocoder search by its zipcode and saves all the new data it finds.

 def perform(account)
    result = Geocoder.search(account.zipcode).first
    if result
      account.latitude  = result.latitude
      account.longitude = result.longitude
      account.city = result.city
      account.state = result.state
      account.save!
    end
  end

To use this in our controller we just call

def create
  account = Account.new(params.require(:account).permit(:name, :zipcode))
  account.save
  GeolocateAccountJob.perform_later(account)
end

And voila, rails makes it that easy.

We can call a job to run at a set time as well, for example to archive an article, mail an email or something Set this up by calling the job like so


GeolocateAccountJob.set(wait_until: Date.tomorrow.noon).perform_later
GeolocateAccountJob.set(wait: 1.week).perform_later

Create a new job that converts an account to pro after it is 5 minutes old

###Getting this on heroku

Steps to make it work in heroku First we create our new heroku application

$ heroku create

Then we have to enable redis on heroku, and set sidekiq’s redis url to the one heroku gives us

$ heroku addons:create redistogo
$ heroku config:set REDIS_PROVIDER=REDISTOGO_URL

Lastly we go on heroku enable the beta pricing and switch our free worker on.

Then we have to add a procfile to tell that worker what to do

#procfile
web: bundle exec thin start -p $PORT
worker: bundle exec sidekiq