Build Robust & Production Quality Applications - Lesson 6: Background Jobs
05 May 2015Background Jobs
Email sending typically is not very fast since we have to rely on some third party application. Waiting can slow up your app and potentially frustrate users so it's best to put non-essential and non-time-sensitive tasks in background jobs.
Since you can web processes and background job processes running locally, you need tp run both the rails server and sidekiq servers to process jobs respectively.
Resque
came out of Github - Resque is our Redis-backed library for creating background jobs, placing those jobs on multiple queues, and processing them later.
Benefits: has admin interface, is powered by Github Delayed Job does not require Redis, both uses a pulling queue Beanstalk and Stalker may be better if you care about speed, as they have a pulling mechanism
Sidekiq is a higher performance background solution than Resque and can even be ported, added on top of resque solution.
Check out the Railscast on Resque for intro.
Sidekiq
In order to use Sidekiq, you must install and run Redis. Once downloaded, run the "$ src/redis-server" in the redis-3.0.2 folder.
You must also gem install sidekiq, and run "bundle exec sidekiq"
When watching the Railscast on Sidekiq, it talks about the creation of workers:
#app/controllers/invitations_controller.rb
class InvitationsController < ApplicationController
before_filter :require_user
def new
@invitation = Invitation.new
end
def create
@invitation = Invitation.create(invitation_params.merge!(inviter_id: current_user.id))
if @invitation.save
InivtationWorker.perform_async
flash[:success] = "You've successfully invited #{@invitation.recipient_name}."
redirect_to new_invitation_path
else
flash[:error] = "Please fill in all inputs."
render :new
end
end#app/workers
class InvitationWorker
include Sidekiq::Worker
def perform(invitation_id)
invitation = Invitation.find(invitation_id)
AppMailer.send_invitation_email(invitation).deliver
end
endBut instead of creating workers, we can just use delayed extentions
#app/controlers/invitations_controller.rb
def create
@invitation = Invitation.create(invitation_params.merge!(inviter_id: current_user.id))
if @invitation.save
AppMailer.delay.send_invitation_email(@invitation.id)
flash[:success] = "You've successfully invited #{@invitation.recipient_name}."
redirect_to new_invitation_path
else
flash[:error] = "Please fill in all inputs."
render :new
end
endSince we aren't running .perform_async on a worker, we need to pass @invitiation.id to the AppMailer:
#app/app_mailer.rb
def send_invitation_email(invitation_id)
@invitation = Invitation.find(invitation_id)
mail to: @invitation.recipient_email, from: "info@myflix.com", subject: "Invitation to join Myflix"
end
endTo run tests, you have to add the following to run them inline:
#spec/spec_helper.rb
require 'sidekiq/testing'
Sidekiq::Testing.inline!