Moving one of my projects over from delayed_job to resque/redis, for reasons I wont go into here, I needed to have a few of my workers on a cron job. I was initially going to use the resque-scheduler plugin, but the fact that it runs as a daemon made me a little nervous. I didn’t want to worry about watching the scheduler process for memory leaks and or crashes, and cron is a proven, reliable, scheduling service in itself.
Basically, I took the same concept from my other post, Recurring delayed_job with cron and applied it to redis, instead of using mysql as I did with delayed_job. It works by manually injecting jobs into the queue without using the Rails environment, saving memory, cpu, and time, and also able to be run externally by the system cron.
In this example I’m going to use a Payment model, which holds payment information, and an ‘update’ method which should be run nightly at 0000. I’m using Rails 3 as well, which uses the ‘mysql2’ gem.
This is the resque worker.
class UpdatePayment
@queue = :update_payment
def self.perform(payment_id)
payment = Payment.find_by_id(payment_id)
if payment
# update payment logic goes here
end
end
end
This is the ruby file that the cron will run. I usually place this in root.rails/lib/crons folder.
require 'redis'
require 'mysql2'
# assuming redis is running on the default port.
# if not, example: redis = Redis.new(:host => "10.0.1.1", :port => 6380)
redis = Redis.new
# Make sure queue exists, if not create it. When clearing a queue with the resque web interface, resque removes the queue, so here we just check to make sure it exists.
if redis.sismember('resque:queues', 'update_payment') == false
redis.sadd('resque:queues', 'update_payment')
end
# Mysql DB information
client = Mysql2::Client.new(:host => "localhost", :username => "root", :database => 'your_project_development')
# query the db for all payment records
results = client.query("SELECT `payments`.* FROM `payments` ORDER BY id asc")
# create a job in the update_payment queue that will update each payment, pass each payment id
results.each do |row|
redis.rpush('resque:queue:update_payment', "{\"class\":\"UpdatePayment\",\"args\":[#{row['id']}]}")
end
And this is what goes in the crontab, which can be accessed by typing ‘crontab -e’ in the console.
# m h dom mon dow command
0 0 * * * /usr/bin/ruby /path/to/your/file/cron_payment_update.rb
For reference:
Redis - redis.io
Resque - github.com/resque/resque
Resque Intro - github.blog/2009-11-03-introducing-resque
Redis Ruby Gem(should get installed when installing resque) - github.com/redis/redis-rb