Setting up Resque in Rails - Step By Step
Here are steps for setting up Resque (based on Redis). The environment also includes Rails, unicorn and activeRecord.
gem 'redis' gem 'resque', :require => 'resque/server' These two gems are needed to setup Redis & Resque. You also need to install Redis. That can be done by brew install redis. Follow the steps to ensure that redis is running.
gem 'dotenv-rails', :groups => [:development] This is needed to load the .env variables in the rails applicaiton. When the app is run using foreman, the .env file is loaded automatically, but other times I found this gem useful.
Edit the ProcFile to Have: worker: env TERM_CHILD=1 RESQUE_TERM_TIMEOUT=10 bundle exec rake resque:work QUEUE=* Here you are saying that worker will run this command. In the command you giving 10 seconds for the worker to finish off any work it has already started All is is doing is running the resque rake task and telling teh rake task to run all queues.
Create a folder in /app called jobs Here add the following
module CsvExportFileMaker @queue = :exports
def self.perform(widget_id) Rails.logger.info "doing Work"
rescue Resque::TermException Rails.logger.error "an error happened. job asked to terminate while doing work" Resque.enqueue(CsvExportFileMaker, widget_id) end end
Here one, we are including the errors file so we can requeue the task incase it is terminated while it is still runnning. Then we are specifyingt eh queue from which it will pull off work. We are also defining a perform method which does the work.
Add dotenv.rb in the initializers directory. In the file add
if Rails.env.development? Rails.logger.info "We ar in development, lets load dotenv" require 'dotenv' Dotenv.load end
Here we r just loading the dotenv gem in dev.
Add resque.rb file in the initializers directory.
Rails.logger.info "In resque.rb conecting to resque url #{ENV["REDISTOGO_URL"]}"
uri = URI.parse(ENV["REDISTOGO_URL"])
Resque.redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password, :thread_safe => true)
Dir["/app/app/jobs/*.rb"].each { |file| require file }
Here we are connecting to redis on init. Then we are loading all the job workers.
Now add resque_auth.rb as another initializer
Resque::Server.use(Rack::Auth::Basic) do |user, password| user == "1" password == "2" end
We are doing this to add basic auth to resque admin portal
mount Resque::Server, :at => "/resque"
This mounts the resque admin portal to our app
Now in uncorn.rb add the following to disconnect and reconnect to Redis.
Add the following to the before_form block
if defined?(Resque) + Resque.redis.quit + Rails.logger.info('Disconnected from Redis') + end
Add the following to the after_fork block
if defined?(Resque) + uri = URI.parse(ENV["REDISTOGO_URL"]) + Resque.redis = Redis.new(:host => uri.host, :port => uri.port, + :password => uri.password, :thread_safe => true) + Rails.logger.info('Connected to Redis') + end
Now add the following rake tasks:
if Rails.env.development? + require 'dotenv/tasks' + task :mytask => :dotenv do + # things that require .env + end +end
+require "resque/tasks" + +task "resque:setup" => :environment do + ENV['QUEUE'] = '*' + + Resque.before_fork do + Rails.logger.info "in resque.rake before fork" + defined?(ActiveRecord::Base) and + ActiveRecord::Base.connection.disconnect! + end + + Resque.after_fork do + Rails.logger.info "in resque.rake after fork" + defined?(ActiveRecord::Base) and + ActiveRecord::Base.establish_connection + end +end + +desc "Alias for resque:work (To run workers on Heroku)" +task "jobs:work" => "resque:work"
Here we are adding resque rake tasks to our tasks. Then we are making sure to disconnect and connect to db in every worker.
Now in our controller add the code to add a job
Resque.enqueue(CsvExportFileMaker, widget_id)
In the .env file add REDISTOGO_URL=redis://localhost:6379/
add the redisToGo plan add a worker.