IRKitly を作った時の知見です。
Heroku の無料プランで cron 処理をするには Heroku Scheduler を使うのが一般的です。
しかし、Heroku Scheduler では分単位で指定することはできません。
ChronoCross
この問題を解決するために Chrono という gem をラップした ChronoCross という gem を作りました。
スレッドを立てて、指定した時間まで sleep することで cron 処理を実現しています。
ChronoCross の gem の中で、Chrono::Trigger を参照しているのが最大の見所です。
問題点
この gem は一見するとうまく動くように見えますが、以下の2つの問題があることがわかりました。
- Heroku の Web プロセスは一定時間アクセスが無いと、プロセスごと落とされてスレッドが止まる
- Heroku は一日一回必ず再起動するので、スレッドを復元しなければならない
1つ目の問題に対しては、New Relic APM | Heroku Dev Center を使って、ping を飛ばし続ける定番の方法で回避しました。
2つ目の問題に対しては、config/initializers に、「DB を select してジョブを登録するスクリプト」を追加することで回避しました。
IRKitly のコード が参考になるかもしれません。
このように Heroku で使うには少しクセがある gem ですが、なんといっても Heroku の Web プロセス 1 dyno で済むのが最大の特長となっています。
その他の方法
sidekiq-cron を使う方法もあるようです。
無料プランで使う場合には、sidekiq プロセスだけで dyno を動かす必要があります。
Unicorn の before_fork に入れる方法もあるようですが、おそらく Web プロセスを寝かさないようにする必要がありそうです。
まとめ
Heroku でも cron 処理をしよう!