どうもこんにちは。
今回は以下の記事で紹介したdelayed_job
で実装したバッチ処理が動かなかった問題を解決したので、備忘録としてまとめたいと思います。
バッチ処理の基本的な手順は以下の記事をご覧ください。
バッチ処理って?
そもそものバッチ処理についておさらいします。
バッチ処理とは、決まった時刻や時間間隔で行う処理のことです。
例えば、「10分間隔でメール送信ジョブを動かす」「決まった時間に過去のデータを削除する」などですかね。
今回のエラーについて
今回のエラーは、「決まった時間に実行したいジョブが実行されなかった」というものです。
概要
config/schegule.rb
に以下のように記述したコードが動きませんでした。
every 10.minute do
runner "Batch::WatchDelayedJob.job_destroy"
runner "Batch::WatchDelayedJob.send_alert"
end
エラー時の状況
AWS ElasticBeanstalkから取得したログから判断した状況について説明します
cronの実行状況
cronの実行は問題なく動作していました。
bundle exec bin/rails runner -e staging '\''Batch::WatchDelayedJob.job_destroy'\''
が10分おきに実行されていたので、「schegule.rb
の記述は反映されているな」と判断できます。
crondサービスの動作確認
amazon Linuxではcronサービスをcrond
と呼ぶらしいです。
ElasticBeanstalkのRailsコンソールにSSH接続して、crondサービスの動作状況を確認しました。
sudo systemctl status crond
実行結果
# sudo systemctl status crond
● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
Active: active (running) since 月 2023-10-02 08:22:26 UTC; 1 day 1h ago
Main PID: 2249 (crond)
CGroup: /system.slice/crond.service
└─2249 /usr/sbin/crond -n
Activeと記載されているので、問題なく動作していそうですね。
rails runnerの動作
次にElasticBeanstalkの実行環境にSSH接続して、直接rails runner
を実行してみました。
実行したコマンドは以下です。
bundle exec bin/rails runner Batch::WatchDelayedJob.job_destroy
これを実行した時に、期待していた処理が正常に動きました。
原因箇所の特定
以上の2箇所の状況から、「schegule.rb
で予約したコマンドが、crondサービスで実行されるものの、rails runner
として実行できていないのでは?」という仮説を立てました。
そのため、私はこう考えました。
「crondサービスを使って、関節的に実行環境のターミナルでrails runnerを実行すればいいじゃん!」ということに気づきました。
なぜなら、「直接であればrails runner
のコマンドを実行できるから。」です。
解決
config/schegule.rb
に以下のようにコードを記述しました。
every 10.minute do
command "cd /var/app/current && export $(cat /opt/elasticbeanstalk/deployment/env) && bin/rails runner Batch::WatchDelayedJob.job_destroy"
command "cd /var/app/current && export $(cat /opt/elasticbeanstalk/deployment/env) && bin/rails runner Batch::WatchDelayedJob.send_alert"
end
command
とすることによって、実行環境のターミナルを叩くことができます。
cd /var/app/current
はソースコードの場所です。
export $(cat /opt/elasticbeanstalk/deployment/env)
は環境情報を吐き出しています。
bin/rails runner Batch::WatchDelayedJob.send_alert"
で処理したいジョブのコマンドを叩きます。
以上の流れで、バッチ処理が正常に動くようになりました。
まとめ
今回のエラーは半日くらい戦っていました。
crondサービス上でrunnerコマンドが動かないのは謎なので、調査をしていきたいと思います。
記事を書いていて思いましたが、日に日に原因の切り分けが上手くなってきているような。。。
以上