resque-scheduler (resqueでcronみたいなことをする)

27th Feb, 2010 | ruby rails resque scheduler

resqueシリーズ。 前回resque-scheduler について少し触れたのだけど。resque-schedulerのメインであるcron的に使う機能について書いてなかったのでメモ。deployについても書いた。

cronと比較して

*nix系のシステムだと、伝統的に、何かを定期的に実行したいcronを使うのだけど、アプリケーションからcronを使う場合、いくつかの使いづらい点がある。

  • アプリケーション本体から離れた場所でcronの動きを管理しないといけない。通常、/etc/crontab 等をメンテナンスしないといけないのだけど、そこはアプリケーションの外側なので、メンテナンスするときにアプリケーション側で使っている方法を使いづらい(SCMもそうだし、deployとかも別で考えないといけない)。
  • cronから起動する場合、起動する環境について考えないといけない。環境変数が代表例。アプリケーションと同じような環境になるように注意しないといけない。

resque-schedulerを使うと、cronでするようなことをアプリケーション内で完結することできる。crontabのようなものをアプリケーション内に置けるので、アプリケーション本体を管理するSCMを使うこともできるし、deployもアプリケーションと常に同じ方法でできるようになる。

ただ、基本的にはcronの動きを踏襲しているので、cronの以下の(場合によっては)負の特徴も引き継いでいる。

  • cronと同じように、指定した時間にresque-schedulerが立ち上がってない場合、その処理は行われない。
  • cronと同じように、同一のタスクが同時に走ってしまう場合がある。例えば、毎分実行するような設定を書いた場合、その処理に1分以上かかってしまった場合、前の処理が終わる前に次の処理が走ってしまう。それが致命的な場合、自分でロック処理を書く必要がある。
  • 複数のresque-schedulerを走らせることが考えられていない。複数のresque-schedulerを実行すると、同じ時刻に同じタスクが複数回走ってしまう。つまり、「冗長化のために、2台のアプリケーションサーバ上でresque-schedulerをそれぞれ動かす」ということができずに、冗長化した構成が取れない。

最後のは、嫌なので、複数のところで走らせても同一のタスクが複数回走らないようなパッチを書いて作者に投げてある。しかし、「冗長化構成が取れるように」ということには賛同を得たのだけど、そのパッチについてはいくつか課題がありそうなので保留になっている。気が向いたらもうちょっと頑張るつもり。

使い方

resque-scheduler を見るのが早いが、crontabで定義するようことをyamlで定義する。そのドキュメントの例を使わせてもらうと、

queue_documents_for_indexing:
  cron: "0 0 * * *"
  class: QueueDocuments
  args: 
  description: "This job queues all content for indexing in solr"

こんな感じになる。この場合、毎日0時0分に、QueueDocumentsというResqueのJobがQueueに入ることになる。ただし、ResqueのQueueに入るだけで、resque-schdulerは実際の実行はしない、ということに注意。Queueを処理するのはResque自体のWorkerの仕事になる。

deployについて

resqueと同じように、resque-scheduler自身には、起動スクリプトみたいなものがついていないので、godやmonitのようなもので管理するのがいいっぽい。

自分はmonitを使って、こんな感じのwrapperを書いて、monitではそのwrapper経由で、起動、停止をしている。