Gemにcapistrano3-delayed-jobがあるのですが、service作る形になっていて、sudoで設定が必要だったり(セキュアにする為、アプリユーザーのsudoはできないようにしている)、OSに依存しそうなので、自前で組んでみました。
seed作った時と同じ要領なので、難しくないですがメモしておきます。
アプリユーザーのcrontabで、サーバー再起動時の自動起動や、落ちた時に自動起動するcronも書いたので一緒に記載しておきます。

Capistranoの設定変更

Capistranoの設定は完了している前提です。
Capistranoを設定して安全にデプロイできるようにする

config/deploy/production.rb

- server 'prod-servername_railsapp', roles: %w[app db web]
+ server 'prod-servername_railsapp', roles: %w[app db web job]

rolesにjob追加。appでも良いけど、複数台にした時の為。

config/deploy.rb

after 'unicorn:restart', 'delayed_job:restart'

Unicornの再起動後に、Delayed::Jobを再起動する。

namespace :delayed_job do
  desc 'Runs bin/delayed_job status'
  task :status do
    execute_delayed_job('status')
  end

  desc 'Runs bin/delayed_job start'
  task :start do
    execute_delayed_job('start')
  end

  desc 'Runs bin/delayed_job stop'
  task :stop do
    execute_delayed_job('stop')
  end

  desc 'Runs bin/delayed_job restart'
  task :restart do
    execute_delayed_job('restart')
  end
end

def execute_delayed_job(arg)
  on roles(:job) do
    within release_path do
      execute :ruby, 'bin/delayed_job', arg
    end
  end
end

deployで使うのはrestartだけですが、capコマンドでstatus/start/stopもできるように追加。

動作確認

ローカルで

% cap -T
cap delayed_job:restart            # Runs bin/delayed_job restart
cap delayed_job:start              # Runs bin/delayed_job start
cap delayed_job:status             # Runs bin/delayed_job status
cap delayed_job:stop               # Runs bin/delayed_job stop

% cap production delayed_job:status
      01 delayed_job: running [pid 8067]

% cap production deploy
01:23 delayed_job:restart
      01 ~/.rvm/bin/rvm ruby-3.0.0 do ruby bin/delayed_job restart
      01 delayed_job: trying to stop process with pid 4503 sending TERM and waiting 20s ...
      01 delayed_job: process with pid 4503 successfully stopped.
      01 delayed_job: process with pid 8067 started.
    ✔ 01 prod-nop_railsapp 9.182s

crontab設定

service作らなかったので、サーバー再起動時に起動されない。
Unicornもアプリユーザーのcronで起動するようにしているので、そこに追加しました。

サーバーで

$ crontab -e
@reboot bash -l -c 'cd ~/app/current/; rm -f tmp/pids/{unicorn,delayed_job}.pid; bundle exec rails unicorn:start; bin/delayed_job start'
*/10 * * * * bash -l -c "~/app/current/cron/start_delayed_job.cron"

また、Unicornは外部監視で落ちた事に気付けるけど、Delayed::Jobは内部監視を入れないと気付けない。内部監視を別途入れるのは手間だし、落ちた時に対応するのも手間なので、cronを作る事にしました。(上記の2行目)
※Unicornも何度か落ちましたが、原因(php-fpmがメモリ使い過ぎ)に対処したので、様子見。

cron/start_delayed_job.cron

#!/bin/sh

BATCH_NAME='start_delayed_job'
LOG_FILE="log/$BATCH_NAME.log"
cd ~/app/current

error_msg=''
write_log () {
	echo -e "`date +"%Y/%m/%d %H:%M:%S"` ($$) [$1] $2" >> $LOG_FILE
	[ $1 = 'ERROR' -o $1 = 'WARNING' ] && error_msg="$error_msg[$1] $2\n"
}

send_error_mail () {
	[ -z "$error_msg" ] && return
	echo -e "$error_msg" | mail -s "[WARNING]$BATCH_NAME report for `hostname`" -r crond warning
	write_log 'INFO' 'Send error mail'
}

start_delayed_job () {
	bin/delayed_job status > /dev/null 2>&1
	if [ $? -eq 0 ]; then
		write_log 'INFO' "Running"
		return
	fi

	bin/delayed_job start > /dev/null 2>&1
	if [ $? -ne 0 ]; then
		write_log 'ERROR' "Start failure: `pwd`/bin/delayed_job"
	else
		write_log 'WARNING' "Start success: `pwd`/bin/delayed_job"
	fi
}

write_log 'INFO' '=== START ==='
start_delayed_job
send_error_mail
write_log 'INFO' '=== END ==='

mailコマンドのwarningは、aliasesで転送先のメールアドレスを設定しています。

これで安心して寝られますね。


今回のコミット内容
https://dev.azure.com/nightonly/rails-app-origin/_git/rails-app-origin/commit/c72848a4fb91c5319b76f9b5755e5a659039955f

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です