この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
Webアプリとは、ユーザのリクエストに対してレスポンスを返す
アプリケーションですが、時にユーザのリクエストに関係なく
処理を行いたいシチュエーションが存在します。
そのような場合、通常「バッチ」と呼ばれるコマンドライン上で
動くアプリを作成します。
私は現在、Webアプリの開発にRailsを使っていますが、
Railsでは、下記のようにモデルとメソッドを指定すれば
特にバッチ用の各種インターフェイスを作成せずとも
Webアプリの設定をDRYに使い回して簡単にバッチを作成することができます。
ruby script/runner -e production ‘ModelClass.method(params)’
script/console コマンドと併せて大変重宝しています。
で、上記のようなバッチを「運用者のコマンドライン上での操作」という
人力を介さず、任意のタイミングで実行したいとき、*nix系OSの場合は
一般的にcronがよく使われます。
02 4 * * * rails_batch.sh
さて、ここで本題。
rufus-scheduler という gem があります。
http://rufus.rubyforge.org/rufus-scheduler/
このgemは、Railsアプリにおいて以下の機能が行えるようになります。
あるモデルのメソッドに対して
・定期実行が可能(○秒/□分間隔)
・cronとしての予約処理が可能
詳しくは上のリンクを見てください。英語が苦手な方でも
Rails & cron がお分かりの方にはすぐに内容がつかめると思います。
さて、この rufus scheduler、従来の cron と比較してどのようなメリット/デメリットがあるでしょうか。
・記述が簡単
・Railsにおけるバッチ処理は基本的にモデルで完結するので、このような記法だとscript/runner よりもより簡潔に書ける
・処理が楽
・script/runner だと、いちいち、重たいRailsのプロセスを立ち上げるが、rufus-schedulerだと、rufus-schedulerが
記述されたアプリ(プロセス)と同じpidで走るので立ち上げが軽い
・記述が柔軟
毎秒/分ごとの処理の記述が、cronやwhile do hoge; sleep SLEEP_TIME; end よりも
構造的に奇麗に記述できる。
と書くと、なかなか良い子のように思えるのですが、このrufus-scheduler、がっつり欠点もあります。
・つられて落ちる
起動しているwebアプリが落ちるとき、webとは関係なく走ってほしいバッチ処理が走らなくなる。
・サブプロセスとして動く
passengerなら問題になりませんが、mongrelで複数のプロセスを走らせているとき、それぞれのプロセスでschedulerが走り
収集がつかなくなる。
といった具合に、長所が「あったらいいなぁ」というものに対して、欠点が「ゆるさない。絶対にだ」というものなので
どうしても、rufus-schedulerには出番がないわけです。
結構いいアプリだと思うのですがね。
不憫なやつです。
とりあえず自分がこれならいけるかも、と思うものは一つあります。
・クローラ
あるバッチをバックグラウンドジョブで走らせる。そのバックグラウンドジョブで走らせているアプリの中で
rufus-schedulerを使った処理を記述し、そのプロセスをkillするまで半永久的に
ほぼ同じ動作を繰り返す。
例えば、クローラとか、WebAPIを叩く処理(例えばtwitterの最新の状態を反映するblogパーツ)
とかは、この処理を使うとぐっと記述しやすくなるのでしょうか。
以前はよく見かけたのですが、日本語の情報もさっぱり見つかりません。
誰かこの子の活躍の場、思いついた方、共有していただけますとありがたいです。