Hello World Resque (Railsにresqueを導入する)


Ruby2.0, Rails4で確認

resqueは非同期処理を簡単に実現してくれるgemです。

とりあえずレスポンスだけ返して実際の処理は後回しにしたい、という場合にresqueが使えます。

resqueの最新バージョンは2.x系ですが、デフォルトでインストールされるのは1.1系なので1.x系での解説をします。

[1.x系の公式ドキュメントはこちらになります。](https://github.com/resque/resque/tree/1-x-stable)

今回はresqueを使ってhello worldを出力するところまでやってみます。

[詳細記事はこちらをご参照ください](http://blog.hello-world.jp.net/?p=895)

## 初期設定

* アプリ作成

```
rails new resque_sample
```

* Gemfile追加

resqueはredisを使用するためあらかじめredisをインストールして起動しておく必要があります。

```Gemfile
gem 'resque'
```

* bundle install

```
./bin/bundle install --path=vendor/bundler
```

* initializer設定

Workerのnamespaceを環境によって分けるように設定しておきます

```config/initializers/resque.rb
Resque.redis = 'localhost:6379'
Resque.redis.namespace = "resque:resque_sample:#{Rails.env}" # アプリ毎に異なるnamespaceを定義しておく
```

## Controller作成

* homeコントローラを作成

```
./bin/rails g controller home
```

* routing設定

```config/routes.rb
get "hello/:message" => 'home#hello'
```

* indexアクション編集

```app/controllers/home_controller.rb
class HomeController < ApplicationController
  def hello
    Resque.enqueue(Hello, params[:message])
    render :text => params[:message]
  end
end
```

## ResqueWorker作成

* resque worker用のディレクトリを作成

```
mkdir app/workers
```

* worker作成

```app/workers/hello.rb
class Hello
  @queue = :resque_sample # Woeker起動時に指定するQUEUE名

  def self.perform(message)
    sleep 5
    logger = Logger.new(File.join(Rails.root, 'log', 'resque.log'))
    logger.info "Hello #{message}"
  end
end
```

* Rakeタスクを追加

```lib/tasks/resque.rake
require 'resque/tasks'
```

* worker起動

QUEUEにworker名を指定します。

```
QUEUE=resque_sample rake environment resque:work

# すべてのworkerを対象としたい場合は*を指定
QUEUE=* rake environment resque:work
```

## 確認

ブラウザから

* [http://localhost:3000/hello/world](http://localhost:3000/hello/world)
* [http://localhost:3000/hello/resque](http://localhost:3000/hello/resque)

にアクセスして

```
tail -f log/resque.log
```

を眺めていると数秒後にログに

```
Hello world
Hello resque
```

が記録されます。

## Daemon化してみる

daemon-spawnというgemを用いることでresqueの処理をdaemon化できます。

* Gemfile追加

requireの指定を忘れないように注意

```Gemfile
gem 'daemon-spawn', :require => 'daemon_spawn'
```

* bundle install

```
./bin/bundle install
```

* daemon起動スクリプトの作成

```bin/resque_worker
#!/usr/bin/env ruby
require File.expand_path('../../config/application', __FILE__)
Rails.application.require_environment!

class ResqueWorkerDaemon < DaemonSpawn::Base
  def start(args)
    @worker = Resque::Worker.new('resque_sample') # 複数のworkerがある場合はカンマ区切りで指定
    @worker.verbose = true
    @worker.work
  end

  def stop
  end
end

ResqueWorkerDaemon.spawn!({
  :processes => 1, # プロセス数の指定
  :working_dir => Rails.root,
  :pid_file => File.join(Rails.root, 'tmp', 'pids', 'resque_worker.pid'),
  :log_file => File.join(Rails.root, 'log', 'resque_worker.log'),
  :sync_log => true,
  :singleton => true,
  :signal => 'QUIT'
})
```

複数のworkerがある場合はカンマ区切りで

```
@worker = Resque::Worker.new('worker1', 'worker2')
```

と記述します。

workerに追加した順番で優先順位が決まるので上記の例だとworker1の方が優先度が高くなります。

* 実行権限を付与

```
chmod 755 bin/resque_worker
```

* daemon起動

```
RAILS_ENV=development ./bin/resque_worker start
```

これでworkerをdaemon化することができました。

再度ブラウザからアクセスすれば正しくログに記録されていきます。

* その他のコマンド

停止

```
RAILS_ENV=development ./bin/resque_worker stop
```

再起動

```
RAILS_ENV=development ./bin/resque_worker restart
```

## まとめ

今回はhello worldをログに残す簡単なサンプルでしたが、resqueを使用することで手軽にジョブキューシステムを導入できました。

レスポンスだけ素早く返して重い処理を後回しにしたい、という場合はresqueの検討をしてみてはいかがでしょうか。

### 参考
* [Hello World Resque (Railsにresqueを導入する)](http://blog.hello-world.jp.net/?p=895)
* [resque / resque](https://github.com/resque/resque)
* [Resqueを利用したRailsでの非同期処理/バッチ処理](http://www.oiax.jp/rails/zakkan/resque.html)
* [Rails3 で resque を使う #1](http://blog.twiwt.org/e/386f1c)
* [RailsでResqueを使ってメルマガ配信の仕組みを作る](http://prototype-beta.com/prototype/entry/23_rails%E3%81%A7resque%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%A1%E3%83%AB%E3%83%9E%E3%82%AC%E9%85%8D%E4%BF%A1%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF%E3%82%92%E4%BD%9C%E3%82%8B)
* [Resqueを利用したRailsアプリを、1台のサーバで複数動かす](http://techracho.bpsinc.jp/baba/2012_11_23/6410)
* [Rails3.2.8 + Resque + Heroku(Redis To Go)](http://qiita.com/shu_0115/items/e4b0ed5043d89cc80f24)
* [[Rails][非同期処理]Resqueをはじめる その3 (Resqueを動かす)](http://namakesugi.blog42.fc2.com/blog-entry-117.html)
* [【Ruby】Railsで重たい処理をバックグラウンドで非同期に処理させるResqueを使ってみた](http://6rats.blog62.fc2.com/blog-entry-91.html)
* [iQONのバックエンドの非同期処理について(具体的な実装編)](http://tech.vasily.jp/2013/02/iqon_backend_resque/)
* [Resqueワーカーをデーモンとして動かす](http://www.oiax.jp/rails/zakkan/resque_worker_as_daemon.html)
* [実録！Railsのはまりポイント10選](http://www.slideshare.net/drecom/edgerails2)
* [Setting up Resque](http://atevans.com/setting-up-resque)