2014年2月27日木曜日

Resque クイックスタート - 簡単に始める Ruby の Job Queue -

Resque っていう Rake と Redis を使った Job Queue があるんだけど、これの味見をしようとしてハマったのでメモ。ハマった原因は Resque 2.0 系をインストールしてしまって混乱した感じ。

Redis インストール

CentOS なので yum で入れる
$ sudo yum --enablerepo=epel install -y redis

Resque インストール

#Gemfile
gem "resque"
$ bundle install --path vendor/bundle
注意:ここで
gem "resque", github: "resque/resque"
などとやってしまうと 2.0系が入って混乱する。上のように rubygems からインストールする。あと github のページも 1.x 系は https://github.com/resque/resque/tree/1-x-stable なので注意。

Job のコード

引数で渡されたメッセージを標準出力に出力するだけのジョブを作る。
#job.rb
class Job
    @queue = :default
    def self.perform(message)
        puts message
    end
end
@queue = :default
ってところで入るキューの名前を指定している。今回は default って名前のキューに入れることにする。

enqueue してみる

上で作った Job に "Hello" って引数を渡すようにしてみた。
#enqueue.rb
require "bundler/setup"
require "resque"
require "./job"

Resque.enqueue(Job, "Hello")
で、実行。
$ ruby enqueue.rb
ちなみに、Resque 2.0系を入れてしまった時はここで
resque.rb:268:in `queue': undefined method `[]' for nil:NilClass (NoMethodError)
となってハマった。

Redis を確認

ちゃんと Redis にキューイングされているか確認してみる。redis のコマンドラインクライアント redis-cli を使う。
$ redis-cli
redis 127.0.0.1:6379> keys *
1) "resque:queue:default"
2) "resque:queues"
何か入ってるので、値を確認してみる。
redis 127.0.0.1:6379> lindex resque:queue:default 0
"{\"class\":\"Job\",\"args\":[\"Hello\"]}"
さっき enqueue したジョブがちゃんと入ってる。ここまでは大丈夫そう。

Worker のコード

次は Redis に入れたジョブを引っ張りだして実行するべく worker を作る。これがちょいと意表をつかれる。

github の README に "Resque workers are rake tasks that run forever." って書いてあるんだけど、Resque の worker は、永遠に動き続ける rake のタスクということだ。なので Rakefile が必要。

こんな感じで書く。
#Rakefile
require "bundler/setup"
require "resque/tasks"

14/7/15 追記:
Rakefile にはジョブを処理するファイル(ここでは Job.rb)も読み込まないといけないので以下も必要
require "./job"

Worker 起動

環境変数経由でいくつかパラメータを渡しつつ rake 実行
$ TERM_CHILD=1 QUEUE=default rake resque:work
Hello
ちゃんと Hello が表示されてる。これは enqueue する時に Job に渡した引数が標準出力に表示されてるってこと。

別のターミナルから再度 enqueue.rb を実行してみる。
$ ruby enqueue.rb
$ TERM_CHILD=1 QUEUE=default rake resque:work
Hello
Hello
こんな感じで、また Hello が表示される。

あとは他のサイトを見ながら worker をデーモン化したり、Web UI を試したりすればいいと思う。

補足など

Redis

Redis ってデータ型によって使えるコマンドが変わるみたいなので要注意。何でもかんでも get しようとすると下のように怒られる。
redis 127.0.0.1:6379> get resque:queue:default
(error) ERR Operation against a key holding the wrong kind of value
まず type コマンドでタイプを調べてデータ型に応じたコマンドを使うのが正解っぽい。ちょっと面倒くさい。
redis 127.0.0.1:6379> type resque:queue:default
list
これは list なので lindex で値を取得できる。

データ型に応じたコマンドは
http://redis.shibu.jp/commandreference/index.html にまとまってる。

Worker の起動コマンド

$ TERM_CHILD=1 QUEUE=default rake resque:work
この書き方分かりにくいけどようするに rake resque:work ってこと。環境変数の TERM_CHILD とか QUEUE とかにパラメータ渡してから rake を実行してる。

TERM_CHILD=1 を付けないと何故か怒られる。http://hone.heroku.com/resque/2012/08/21/resque-signals.html に何か書かれているっぽいが未調査。

QUEUE はキューの指定している。今回は default キューについて処理する。*にすると全てのキューを処理できるっぽい。

STDOUT に進捗を表示させたい場合は VERBOSE オプションを付ければいいっぽいが、実際に付けてみると DEPRECATION WARNING って言われて怒られてしまう。
$ TERM_CHILD=1 VERBOSE=1 QUEUE=default rake resque:work
*** DEPRECATION WARNING: Resque::Worker#verbose and #very_verbose are deprecated. Please set Resque.logger.level instead
怒られるが表示はされる。もし WARNING が気になるようなら Rakefile に以下を追記すれば VERBOSE を使わなくても同じことができる。
require "resque"
Resque.logger = Logger.new(STDOUT)
Resque.logger.level = Logger::DEBUG

Rakefile

特に task の定義していないのに rake resque:work で実行できてしまうのは、 resque/tasks 内で resque:work ってタスクが定義されるから。

0 件のコメント :

コメントを投稿