Herokuでプログラムをスケジュール起動する場合は、Heroku Schedulerが主に使われると思いますが、Heroku Scheduler自体はベストエフォート型のサービスだったり、細かい時間の制御ができなかったり色々と融通が利かない部分があります。ということで今回はClockwork + Resqueでバッチ処理を作ってみます。

大枠としてはClockworkがcronの役割で、起動時刻になったらResqueでエンキューし、Workerがデキューして処理を実行するという流れです。こうすることで、バッチ実行自体をスケールさせることが出来る上にClockworkの処理は最小限になり、I/O待ち等が発生しないため、安定して処理を実行できます。Clockworkのようなスケジュール用のプロセスは、マルチプロセスだと重複実行の可能性があり、重複実行を防ぐためのロック機構も複雑になるためシングルプロセスで実行することを推奨しています。また、Clockwork自体にバッチ処理を実行させることも出来ますが、並列処理が実行できない可能性があることから推奨されていません。threadオプションを使えば、非同期に並列処理ができますが、スケーラビリティを考えるとWorker方式の非同期処理の方が良いです。

使い方

Gemfileに以下を記述してbundle installすればOK

clockworkのスクリプトはこんな感じで書く

workerはこんな感じで記載

Procfileはこのように記述すればOK

HerokuでClockworkを使う際の注意

HerokuはデフォルトのタイムゾーンがUTCになります。

JSTでClockworkの起動時刻を制御したい場合は、以下のように環境変数を設定すればOK

そうするとタイムゾーンが変わります。

あと、Herokuの仕様の「1日1回再起動」というのもバッチ処理においては気になるところです。Clockwork側、Worker側にはちゃんとログを仕込んでおいて、実行ログを監視するのは必須ですかね。

参考URL