Delayed Job is a great and simple solution for background jobs in a Rails application. But if you don’t have the memory or resources to run a background thread 24hrs on a server what do you do?
We were in a similar situation for a client, who was strictly on a shoe string budget, running off Heroku. The background job was to process some applications, verify and sent emails if they had errors. This was to be done once a day. Running a background job just for this was a bad choice.
Another option was to run this as a rake task, at a set time, use Heroku Scheduler to run this at 04:00am every day. But we wanted to try a bit more generic solution.
We decided to stick to write Delayed Job classes, so that in future, it can serve 2 purposes
- For more background processing, more jobs we just have to write new classes with
perform
methods - When the app is moved into it’s own private hosting VPS, run a background thread more often, to scale it.
So delayed job it was!
But in the current setup, we had to run the jobs as a rake task, triggered once a day at a specific time, while leaving room for a full fledged background process in the future.
Looking at the delayed_job source at Github we figured that this could be easily implemented. It internally creates a Delayed::Worker
class and works off all the jobs in the delayed_jobs
table.
The solution was really simple.
Create a rake task in lib/tasks/delayed_job.rake
# File lib/tasks/delayed_job.rake
namespace :delayed_job do
desc 'Run Delayed job worker'
task work: :environment do
worker = Delayed::Worker.new
worker.work_off #by default runs 100 rows
end
end
For more information on the sources:
-
The rake task for starting delayed job - delayed/tasks.rb
-
The Delayed::Worker start - delayed/worker.rb
-
Delayed::Worker work_off definition - delayed/worker.rb#work_off
Credits: Header photo by Elisa Michelet on Unsplash.