I'm wondering what's the best way to gracefully restart delayed_job consumers after a new code push? I'm pushing code with capistrano and I know there are commands to restart, but if there are jobs currently running, the command either hangs (and my deploy takes forever) or it forcefully quits the currently running job and I lose data.
Ideally I'd like my deploy to happen like this:
cap deploy
and version 2 code is pushed out to new serversI've tried to insert some code to restart before a job runs by checking the current revision of the code but every time I do that, it just dies and doesn't actually restart anything. Sample code below:
def before(job)
# check to make sure that the version of code here is the right version of code
live_git_hash = LIVE_REVISION
local_git_hash = LOCAL_REVISION
if live_git_hash != local_git_hash
# get environment to reload in
environment = Rails.env # production, development, staging
# restart the delayed job system
%x("export RAILS_ENV=#{environment} && ./script/delayed_job restart")
end
end
It detects it just fine but it dies on the shell call. Any ideas?
Thanks!
Came up with a solution that works.
I have a base class that all of my delayed jobs inherit from called BaseJob
:
class BaseJob
attr_accessor :live_hash
def before(job)
# check to make sure that the version of code here is the right version of code
resp = HTTParty.get("#{Rails.application.config.root_url}/revision")
self.live_hash = resp.body.strip
end
def should_perform()
return self.live_hash == GIT_REVISION
end
def perform()
if self.should_perform == true
self.safe_perform()
end
end
def safe_perform()
# override this method in subclasses
end
def success(job)
if self.should_perform == false
# log stats here about a failure
# enqueue a new job of the same kind
new_job = DelayedJob.new
new_job.priority = job.priority
new_job.handler = job.handler
new_job.queue = job.queue
new_job.run_at = job.run_at
new_job.save
job.delete
# restart the delayed job system
%x("export RAILS_ENV=#{Rails.env} && ./script/delayed_job stop")
else
# log stats here about a success
end
end
end
All base classes inherit from BaseJob
and override safe_perform
to actually do their work. A few assumptions about the above code:
Rails.application.config.root_url
points to the root of your app (ie: www.myapp.com)/revision
(ie: www.myapp.com/revision)GIT_REVISION
that your app knows aboutWhat I ended up doing was putting the output of git rev-parse HEAD
in a file and pushing that with the code. That gets loaded in upon startup so it's available in the web version as well as in the delayed_job consumers.
When we deploy code via Capistrano, we no longer stop, start, or restart delayed_job consumers. We install a cronjob on consumer nodes that runs every minute and determines if a delayed_job process is running. If one isn't, then a new one will be spawned.
As a result of all of this, all of the following conditions are met:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With