I don't have time to read and I want to jump immediately to the solution.
The problem
From the day I started using DelayedJob in combination with God, I faced the problem to restart the god
group every time I deployed a new application release.
In fact, when a rake task (God runs DelayedJob using the rake jobs:work
task, here's the config) is started, it loads the entire Rails environment and keeps it in memory as long as the process is running. When you deploy a new version, if you don't restart the rake task, DelayedJob continues to run with the previous Rails version environment.
To restart a task/group in God:
$ god restart GROUP_NAME
Speaking about my servers, the problem is that God runs as root while Capistrano deploys new releases using a not-root not-sudo user, for security purposes. In practice, it means I can't use the Capistrano sudo
command because the deploy user is not in the sudoers list. Fortunately, the solution exists and is to run the command as su -c <command>
.
The gotcha here is that when you use su
you have to handle the remote server root password prompt. Thanks to Capistrano, this is as easy as pie.
Here's the method I created to run the command.
The solution
# Runs +command+ as root invoking the command with su -c
# and handling the root password prompt.
#
# surun "/etc/init.d/apache reload"
# # Executes
# # su - -c '/etc/init.d/apache reload'
#
def surun(command)
password = fetch(:root_password, Capistrano::CLI.password_prompt("root password: "))
run("su - -c '#{command}'") do |channel, stream, output|
channel.send_data("#{password}n") if output
end
end
And here's the final Capistrano/DelayedJob/Run code fragment.
namespace :god do
desc "Restart the god group 'GROUP_NAME'"
task :restart, :roles => :app do
surun "god restart GROUP_NAME"
end
end
after "deploy:restart", "delayed_job:restart"