Então você já fez a feliz escolha de tratar seu processamento em background com Delayed Job, ótimo! Mas como ter certeza que esse processamento vai continuar acontecendo enquanto você estiver dormindo? E se o o processo do Delayed Job cair, você vai acordar de madrugada e levantá-lo na mão? Eu não faria isso, gosto do meu sono. Qual a solução então?
Não é nenhuma novidade para nós, rubyistas e railers, que existem soluções como o God para fazerem o trabalho de monitoramento de processos. No entanto, existem outras soluções, como o Bluepill. O Bluepill é uma ferramenta de monitoramento de processos assim como o God, mas diferente dele, não tem memory leak, segundo seus autores.
Bem, como não quero acordar de madrugada para levantar meu processo do Delayed Job na mão, e também não quero ficar restartando um processo do God por causa de memory leak, resolvi usar o Bluepill. Mas como uso o Bluepill para monitorar o Delayed Job?
Para configurar o Bluepill para monitorar o Delayed Job, e usar o Capistrano para automatizar algumas tarefas, temos basicamente 4 passos:
- Instalar e configurar o Delayed job
- Instalar e configurar o Bluepill
- Escrever a receita de capistrano para o Bluepill
- Setar algumas coisas do arquivo /etc/sudoers
Vamos dar uma olhada em detalhes em cada passo.
Instalação e configuração do Delayed Job
Instalar e configurar o Delayed Job é super simples, basta ler o README do projeto, que está bem claro. Recomendo também assistir ao RailsCast sobre o Delayed Job. Foi de lá que tirei a informação de usar o fork do Delayed Job da Collective Idea ao invés da versão do repositório original.
Instalação e configuração do Bluepill
Instalar o Bluepill também não tem muito segredo, basta você ler o README do projeto e seguir os passos que estão descritos lá.
Na parte da configuração, você pode ver as opções também no README do projeto. No meu caso, esse arquivo está em RAILS_ROOT/config/production.pill
.
Bluepill.application("my_app") do |app|
app.process("delayed_job") do |process|
process.working_dir = "/home/deploy/my_app/current"
process.start_grace_time = 10.seconds
process.stop_grace_time = 10.seconds
process.restart_grace_time = 10.seconds
process.start_command = "ruby script/delayed_job -e production start"
process.stop_command = "ruby script/delayed_job -e production stop"
process.pid_file = "/home/deploy/my_app/shared/pids/delayed_job.pid"
process.uid = "deploy"
process.gid = "deploy"
end
end
No entanto, eu tive um pequeno problema com a interação do Bluepill e o Delayed Job. Ao passar a flag -e production
para o Delayed Job, ele não a estava interpretando direito. Você pode ver mais detalhes sobre isso numa issue que abri no repo do Delayed Job.
A primeira solução que pensei, foi usar RAILS_ENV=production ruby script/delayed_job start
, no entanto por algum motivo que ainda desconheço, isso não funcionou.
A solução que cheguei então para resolver esse problema, foi modificar o arquivo que está em RAILS_ROOT/script/delayed_job
para o seguinte:
#!/usr/bin/env ruby
# TODO improve the line of code below
# The line below is just a hack while we wait the delayed job guys answer the following issue
# http://github.com/collectiveidea/delayed_job/issues#issue/38
ENV['RAILS_ENV'] ||= "production"
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require 'delayed/command'
Delayed::Command.new(ARGV).daemonize
Como a flag -e production
não estava sendo interpretada direito no Delayed Job, estou setando na mão o RAILS_ENV
para production
(linha 6), portanto estou supondo que você só está usando o Bluepill para monitorar processos do Delayed Job em environment igual a production.
Receita do Capistrano para o Bluepill
Para automatizar as tarefas de ligar e desligar o Bluepill, escrevi a seguinte receita de capistrano:
# deploy credentials
set :user, "deploy"
set :deploy_to, "/home/deploy/#{application}"
set :use_sudo, false
set :rails_env, "production"
# Bluepill related tasks
after "deploy:update", "bluepill:quit", "bluepill:start"
namespace :bluepill do
desc "Stop processes that bluepill is monitoring and quit bluepill"
task :quit, :roles => [:app] do
sudo "bluepill stop"
sudo "bluepill quit"
end
desc "Load bluepill configuration and start it"
task :start, :roles =>[:app] do
sudo "bluepill load /home/deploy/my_app/current/config/production.pill"
end
desc "Prints bluepills monitored processes statuses"
task :status, :roles => [:app] do
sudo "bluepill status"
end
end
Note que ao invés de usar o método run
do capistrano, estou usando o método sudo
. Isso porque o comando bluepill deve ser rodado como root. Isso nos leva para o próximo tópico.
/etc/sudoers
Já que eu preciso rodar o comando bluepill como root, vou ter que mudar o meu set :user, "deploy"
para set :user, "root"
? Acho melhor não, não gostamos de dar acesso root para qualquer coisa, mesmo para deployment. Então, como fazer? Simples, basta editar seu arquivo de sudoers.
Para isso, você precisa usar o comando visudo
para abrir e editar o arquivo /etc/sudoers
. Uma vez com o arquivo aberto, adicione a seguinte linha no final do arquivo:
deploy ALL=(ALL) NOPASSWD: /usr/local/bin/bluepill
Pronto, agora o usuário deploy já pode fazer sudo bluepill
sem precisar de senha. Problema resolvido sem colocar a segurança da sua máquina em risco. 😉
Depois de ter feito esses 4 passos, você está pronto para dormir a noite sem se preocupar com seu processo do Delayed Job. E quando quando quiser saber como está o status dos seus processos monitorados, basta usar a seguinte task do capistrano na sua máquina local:
cap bluepill:status
E você? Quais soluções você usa para dormir em paz?
Update: Se você está tendo problemas em restartar o Bluepill com o capistrano, dê uma olhada aqui.