Ruby, Mina, Puma e Upstart ftw!
Faz um tempo que mudei do Unicorn para o Puma, o motivo é porque precisavamos de um servidor multi-thread, dado que o Unicorn é baseado em fork de processos..
Assim como o Unicorn, precisamos fazer o controle de pid files com Puma, na net a gente encontra vários scripts para fazer isso, porém eu prefiro utilizar a gema mina-puma já que também uso o mina para deploys.
Basta incluir gem 'mina-puma', require: false
no Gemfile
e então já ganhamos algumas tarefas pra iniciar, parar, e reiniciar o Puma.
Usamos um serviço de CI para rodar testes e fazer deploy no staging, porém, vira e mexe acontecia deste último falhar na task de reinicar o Puma retornando a mensagem Puma is not running!
.
Para contornar isso, simplesmente adicionei uma verificação antes da task no config/deploy.rb
:
to :launch do
# ....
result = capture("[ -e #{deploy_to}/#{shared_path}/tmp/sockets/pumactl.sock ] && echo 'running' || echo 'not running'")
if result.include?('not')
puts 'not running'
invoke :'puma:start'
else
puts 'running'
if rails_env == 'staging'
puts 'puma:restart'
invoke :'puma:restart'
else
puts 'puma:phased_restart'
invoke :'puma:phased_restart'
end
end
end
Na primeira linha checamos se o servidor de aplicação está rodando e então iniciamos ou reiniciamos..
Estava tudo ok, até que um dia precisamos reinicar o servidor e ele não subiu o Puma também, ou seja, site off. Como solução eu criei um serviço no Upstart do servidor para executar o mesmo script que a gema mina-puma
roda:
# /etc/init/puma.conf
description "Puma"
start on runlevel [2345]
stop on runlevel [016]
respawn
env APP_BASE_PATH=/ebs/storage/www/my_app
env APP_ENV=staging
post-start script
exec su - deploy -c "cd $APP_BASE_PATH/current && bundle exec puma -q -d -e $APP_ENV -b unix://$APP_BASE_PATH/shared/tmp/sockets/puma.sock -S $APP_BASE_PATH/shared/tmp/sockets/puma.state --pidfile $APP_BASE_PATH/shared/tmp/pids/puma.pid --control unix://$APP_BASE_PATH/shared/tmp/sockets/pumactl.sock"
end script
post-stop script
exec su - deploy -c "cd $APP_BASE_PATH/current && bundle exec pumactl -S $APP_BASE_PATH/shared/tmp/sockets/puma.state stop; rm -f $APP_BASE_PATH/shared/tmp/sockets/pumactl.sock"
end script
Agora ao ligar o servidor o Puma será inicado automaticamente e também podemos usar sudo service puma start
e sudo service puma stop
para iniciar/parar.
Abs.