Use systemd to start and monitor puma

Puma 4 is no longer maintained, and Puma 5 removed the option to run
Puma as as daemon. That means that, in order to upgrade, we need to rely
in a process monitoring tool. We're using systemd because it's installed
by default in most (all?) operating systems running Consul Democracy on
production and it's supported by both Puma and the capistrano3-puma gem.

Using systemd means Puma will be automatically started whenever it
crashes, so we no longer need the changes done in commit 40b3c9f2c and
we can now use the default tasks configuration in capistrano3-puma and
capistrano3-delayed-job.

Since Puma is also started automatically when booting the system, we
don't need a cron job to do so anymore and can remove it from the
`schedule.rb` file.
This commit is contained in:
Javi Martín
2023-09-08 17:08:28 +02:00
parent 2aff3b73f9
commit d8d4c1e9a4
4 changed files with 27 additions and 13 deletions

View File

@@ -15,7 +15,7 @@ require "rvm1/capistrano3"
require "capistrano/puma"
install_plugin Capistrano::Puma, load_hooks: false
install_plugin Capistrano::Puma::Daemon
install_plugin Capistrano::Puma::Systemd
#SCM: Git
require "capistrano/scm/git"

View File

@@ -49,6 +49,7 @@ set :fnm_install_node_command, -> { "#{fetch(:fnm_setup_command)} && fnm use --i
set :fnm_map_bins, %w[bundle node npm puma pumactl rake yarn]
set :puma_conf, "#{release_path}/config/puma/#{fetch(:rails_env)}.rb"
set :puma_systemctl_user, :user
set :delayed_job_workers, 2
set :delayed_job_roles, :background
@@ -57,9 +58,6 @@ set :delayed_job_monitor, true
set :whenever_roles, -> { :app }
namespace :deploy do
Rake::Task["delayed_job:default"].clear_actions
Rake::Task["puma:smart_restart"].clear_actions
after "rvm1:hook", "map_node_bins"
after :updating, "install_node"
@@ -68,12 +66,7 @@ namespace :deploy do
after "deploy:migrate", "add_new_settings"
after :publishing, "setup_puma"
after :published, "deploy:restart"
before "deploy:restart", "puma:restart"
before "deploy:restart", "delayed_job:restart"
before "deploy:restart", "puma:start"
before "puma:smart_restart", "stop_puma_daemon"
after :finished, "refresh_sitemap"
desc "Deploys and runs the tasks needed to upgrade to a new release"
@@ -81,6 +74,9 @@ namespace :deploy do
after "add_new_settings", "execute_release_tasks"
invoke "deploy"
end
before "deploy:restart", "puma:smart_restart"
before "deploy:restart", "delayed_job:restart"
end
task :install_ruby do
@@ -169,10 +165,30 @@ end
desc "Create pid and socket folders needed by puma"
task :setup_puma do
on roles(:app) do
on roles(fetch(:puma_role)) do
with rails_env: fetch(:rails_env) do
execute "mkdir -p #{shared_path}/tmp/sockets; true"
execute "mkdir -p #{shared_path}/tmp/pids; true"
end
end
after "setup_puma", "puma:systemd:config"
after "setup_puma", "puma:systemd:enable"
end
# Code adapted from the task to stop the daemon in capistrano3-puma
desc "Stops the Puma daemon so systemd can start the Puma process"
task :stop_puma_daemon do
on roles(fetch(:puma_role)) do |role|
within release_path do
with rails_env: fetch(:rails_env) do
if test("[ -f #{fetch(:puma_pid)} ]") &&
!test("systemctl --user is-active #{fetch(:puma_service_unit_name)}") &&
test(:kill, "-0 $( cat #{fetch(:puma_pid)} )")
info "Puma: stopping daemon"
execute :pumactl, "-S #{fetch(:puma_state)} -F #{fetch(:puma_conf)} stop"
end
end
end
end
end

View File

@@ -12,7 +12,6 @@ state_path "#{rails_root}/tmp/pids/puma.state"
stdout_redirect "#{rails_root}/log/puma_access.log", "#{rails_root}/log/puma_error.log", true
bind "unix://#{rails_root}/tmp/sockets/puma.sock"
daemonize
threads 0, 16
workers 2

View File

@@ -40,7 +40,6 @@ every 1.day, at: "3:00 am", roles: [:cron] do
end
every :reboot do
command "cd #{@path} && bundle exec puma -C config/puma/#{@environment}.rb"
# Number of workers must be kept in sync with capistrano's delayed_job_workers
command "cd #{@path} && RAILS_ENV=#{@environment} bin/delayed_job -m -n 2 restart"
end