この記事について
Heroku上で、Scheduler Add-Onではなくcustomのschedulingでjobを動かすのに、
PythonでAPSchedulerを使ってみたので、詰まった点などをまとめる。
Scheduling Jobについて
前提知識として、Herokuのscheduling jobの設定について
設定方法としては下記の2種類がある。
- HerokuのScheduler Add-Onを使う
- 自分でclock processを実装する
1.2.の違いは、
- ある程度決まり切った間隔のschedulingなら使える(毎日、毎時、10分毎など)
- 1.より複雑なschedulingをする場合(月、水、金とか、毎2時間毎など)
今回自分は細かい設定をしたかったので、2.で設定した。
PythonのAPSchedulerの実装
pipでのinstallなどは、User Guideや
Herokuのヘルプページに載っているのでここでは省略。
scheduling jobの呼び出しは2種類あって、
- add_job()を使う
- scheduled_job()を使う
scheduled_job()の実装方法は上記のHerokuのヘルプページに載っているのだけど、
scheduled_job()を書いてから、そのすぐ下にschedulingしたいタスクを書く記法のよう。
私はadd_job()の方を使って、さらに別のpyファイルに書いてあるモジュールを呼び出すようにした。
そのときの記法としては下の感じ
(別のpyファイルをmysample.py、schedulingしたいタスクをmytask()とする)。
import os,mysample
from apscheduler.schedulers.blocking import BlockingScheduler
if __name__ == '__main__':
sched.add_job(mysample.mytask,'cron', day_of_week='mon', hour='1-3', minute='5')
sched.start()
ここで最初詰まったのが、add_jobに渡すのはモジュールそのものであるという点。
どういうことかというと、add_jobで下記のように渡すと、モジュールの実行結果が渡ってしまい、
全然scheduling jobにならない(herokuでprocessをscaleした瞬間に実行されてしまう)。
...snip...
sched.add_job(mysample.mytask(),...
上の実装で実行すると、Herokuのlogに下記のように出力される。
TypeError: func must be a callable or a textual reference to one
このエラーで調べていて、stackoverflowに同じ質問が載っていたのでそれで分かった。
もしmytask()に引数を渡す必要があったら、
add_job()の引数にargs, kwargsというのがあるのでそれを使えばOKのよう。
cronのパラメーターについて
Herokuのヘルプページを見れば、schedulingのtriggerとして、
'interval'と'cron'があるのが分かるが、
cronのパラメーターにどういう値を設定出来るかが分からなくてちょっと探した。
下記ページに書いてあった。
apscheduler.triggers.cron
細かく設定できるのが分かる。
scheduling jobを動かす
実際に動かすときは、Procfileも下記のように変える。
clock: python myschedulejob.py
Herokuにdeploy出来たら、下記を実行する。
$ heroku ps:scale clock=1