Rails でプロジェクトを作成しているとき、一定期間バッチを止めたくなることとか、あると思います。そのようなときは、通常なら server に ssh ログインして crontab を書き直したりすることになりますが、その定期的な処理を気軽に on/off したい、ということはありませんか?
特にエンジニアでない方が batch の実行/不実行を制御したい場合、画面でそれが行えると便利です。ですが web フォームから crontab の中身を直接制御することはできません。
それを「擬似的に」行うための実装を、サンプルコードとして実装する機会がありましたので、共有致します。
利用する Gem
rails new
した後に生成された Gemfile
に、下記 2つの Gem を追加しています。
model の説明
- BatchModel : 実際に動かしたい Batch 処理の中身が記述されている
- BatchConfig:上記を制御する情報が入っている
つまり、以下の内容になっています。
- crontab(whenever) に書かれているのは、
BatchConfig
内に書かれている処理 - crontab を webページから気軽に編集できないため、
BatchConfig
内の処理は定期的に必ず実行される -
BatchConfig
内の処理で、BatchModel
内の処理を呼び出すかどうかを制御していて、その呼び出すための情報は DB に入っており、webページから編集可能になる
新たな処理を追加するには
現在のサンプルプロジェクトでは、1日1回、及び、1時間1回の間隔で、batch 処理が走るように設定されています。
プロセスを追加するには、以下の方針で行えば可能です(開発環境の場合。適切に capistrano 等でデプロイタスクを組んでいたら、本番ではいくつかのコマンドは自動で実行されるはずです)
新たな batch 処理を追加したい
- まずは適当なmodelに処理を作成して、
bin/rails c
でそれが期待通り動くことを確かめる -
db/fixtures/batch_config.rb
(ファイル)に、その処理内容と実行タイミングを記述する -
bin/rake db:seed_fu
を実行する -
bin/rails s
でサーバを起動し、ブラウザからhttp://(domain)/batch_config
にアクセスして、バッチの実行順を制御する
新たな起動タイミングを設定したい
-
config/schedule.rb
(ファイル)に、新たな crontab の記述を追加する。その際、その実行タイミングに名前をつける(サンプルコードでは daily, hourly) -
db/fixtures/batch_config.rb
(ファイル)の、実行タイミングの部分を変更する -
bin/rake db:seed_fu
を実行する -
RAILS_ENV=development bundle exec whenever --update-crontab
を実行して、crontab の中身を書き換える
改修ポイント
- DB 内に処理名が書いてあって、それを eval で実行している箇所がある。ここを web から編集することはないが、もう少しバグに強い書き方があるかもしれない
- 本番で複数台のサーバがある場合、batch を挙動するサーバを指定することができる。また負荷が高い場合はバッチ処理を分けたい。batch を起動するサーバのIPを記録するカラムは用意しているので、「自分のIPが指定されている処理だけ実行」という処理を BatchConfig に追加する