読者です 読者をやめる 読者になる 読者になる

セロリ食べたい

とりあえず作りました

Kue をつかってみた

node.js でペロペロと遊んでいるのですが、以下のようなことをやりたいと思いました。

  • バックグラウンドで行いたい処理をキューに追加していって、それを順次実行したい
  • それをきれいに管理したい
  • 指定した時間が経過したあとに、遅れて処理を実行したい(5秒後にほにゃらら、みたいな)

パッケージでそんなものがないかと探してみると、Kue というものが見つかったので使ってみました。Kue ってなんて読むんだろう。くえ?きゅー?くー?

Kue は npm をつかって簡単にインストールできます。

npm install kue

Kue ではひとつの処理を job と呼んでいるみたいです。job の管理に redis を使うようなので、redis も使えるように設定しておく必要があります。homebrew なり MacPorts なりでインストールするとよいでしょう*1。ここではその手順は省略します。

僕は node.js のアプリケーションを coffeescript で書いているので、以下の例はすべて coffeescript のコードです。

まず、自分のアプリケーションで Kue を使えるようにモジュールを読み込み、createQueue関数でキューを作ります。さらに、'kue.app.listen 3000' と記述しておくと、ポート3000で Web インターフェイスが起動します。キューに追加した job や実行中の job の一覧がブラウザで確認できるので便利です。

kue = require 'kue'
jobs = kue.createQueue()

kue.app.listen 3000

Kue では job の実際の処理をキュー(jobs)の process という関数で設定します。process 関数では第一引数に job の名前を、最後の引数に処理内容を定義した関数を指定します。0.1秒ごとに100までカウントを増やす hoge job と fuga job を設定しました。この job はカウントをひとつ増やすたびに job に設定された値を console.log で出力します。job を設定するときには、一度にそのjobをいくつまで並行に動かしてよいか指定することができます。以下の例では、 fuga job を3つまで並行に動かしてよいと指定しています。

process = (job, done) ->
    progressMax = 100
    next = (i) ->
        console.log "#{job.data.title}(#{job.data.id}) [#{i}/#{progressMax}]"
        job.progress i, progressMax
        if i == progressMax
            done()
        else
            setTimeout ->
                next i+1
            , 100
    next 0

jobs.process 'hoge', process
jobs.process 'fuga', 3, process

以下のようにして job を登録します。キューの create 関数の引数には、作成する job の名前とそれに与える値をオブジェクトで指定します。job に起きたイベントに応じて実行したい処理を設定することもできます。以下の例では job が終了したら 'complete hoge' と標準出力に出力するようにしました。最後に save 関数を呼ぶことで、job が redis に登録されます。以下の例では hoge job を5つ登録しています。

jobs.create('hoge',
    title: 'hogehoge'
    id: i
).on('complete', ->
    console.log 'complete hoge'
).save() for i in [1..5]

遅れて実行したい job は以下のようにして登録できます。delay(5000) のようにdelay関数でミリ秒単位の遅延時間を指定するだけです。以下の例では、fuga job は5秒待ってから処理を実行します。遅延実行する job を登録した際は、遅延 job の確認を何ミリ秒おきに行うか、キューの promote 関数で指定する必要があります。引数に何も指定しないと5秒おきに確認します。以下の例では 100ミリ秒おきに確認するように指定しました。

jobs.create('fuga',
    title: 'fugafuga'
    id: i
).on('complete', ->
    console.log 'complete fuga'
).delay(5000).save() for i in [1..5]

jobs.promote 100 # default 5000(ms)

以上、簡単に Kue を使ってみたの例でした。コードは github においてあります。https://github.com/slightair/hello-kue

*1:関係ないですが僕はまだ MacPorts をつかっています。クリーンインストールをするタイミングで homebrew に移行するんだ!とずっと思っているのですが、なかなかその機会はやってきません。

heroku を使ってみる

ちょっと試しに heroku を使ってみたいなぁと思ったので登録して動かすとこまでやってみた。その時のメモをここに記す。

はじめに heroku のサイトにいって登録する。メールアドレスのみ入力するフォームが表示された。シンプルだなぁ。すぐにメールがやってきて、そこに書かれたリンクを開くとパスワードを入力するフォームが表示される。はい、登録できました。

そのまま、My Apps という画面にやってきた。QuickStart Guide というものに目がついたのでつついてみる。Heroku を使うための手順が表示されたので、これに沿って操作をしてみよう。

まず、Heroku Toolbelt というものをインストールするらしい。下調べした時はRubygemsで何かをインストールする記事を見かけたけれど、MacOSX、Windows、Ubuntu Linux、その他それぞれに用意されているようだ。僕の環境は MacOSX なので OSX package をダウンロードしてインストールする。

Heroku Toolbelt をインストールするとターミナルで heroku コマンドが使えるようになった。 QuickStart Guide に従い、このコマンドを使って heroku にログインする。

> heroku login

上のコマンドを入力し実行すると、いろいろ聞かれるので答えていく。メールアドレスとパスワードを入力した後に公開鍵がいくつか見つかったけどどれを使うの?と聞かれたので一度コマンドを中止した。なんとなくサービスごとに公開鍵と秘密鍵の組を使い分けているので、 heroku 用に新しいものを作る。

> ssh-keygen -t rsa

こちらもぺろぺろと質問に答えていって鍵の組を作った。もう一度 heroku のコマンドを実行して作業をすすめる。さっき作った公開鍵を選択すると、公開鍵が送信され、認証成功と出てコマンドが終了する。

次の手順はいよいよアプリケーションの配置らしい。今回はなんとなく最近いじっている node.js のアプリケーションを配置してみることにする。サポートしているらしいプログラミング言語やフレームワークが表になっていたので、この中から node.js を選択する。ガイドにはnode.jsのアプリケーションコード例なども載っている。すでに動くアプリケーションがあるのでその節は読み飛ばした。

アプリケーションを配置する際に Procfile というファイルを用意する必要があるようだ。heroku に配置するアプリケーションをどう動かせばよいのか教えてあげるファイルなのだろうか。ガイドに習い、以下のように記述した。

web: node app.js

Procfile を作った後は foreman というコマンドで試すことができるらしい。以下のようなコマンドを実行するとサーバが起動したようなログが表示された。多分大丈夫なんだろう。

foreman start

今度こそ heroku にアプリケーションを配置できそうだ。git で heroku にアプリケーションを push する。すでに配置しようとしているアプリケーションは git でバージョン管理しているのでガイドにあるような git init などのコマンドは実行しなかった。さっき作った Procfile だけバージョン管理対象に追加してコミットしておく。その後以下のコマンドを実行した。

heroku create --stack cedar

cedar ってなんだろう。コマンドを実行するとなんらかのURLが表示された。とりあえず heroku の git remote の設定は追加されたようだ。早速 push してみよう。

あら、push できなかった。そういえば heroku につなぐときにはさっき作った公開鍵・秘密鍵の組を使ってねという設定をするのを忘れていた。

~/.ssh/config にその設定を記述する。以下のような感じでよいだろう。

host heroku.com
hostname heroku.com
user git
identityfile ~/.ssh/id_rsa_heroku

identityfile のところには自分が作ったファイルのパスを書く。設定が終わったらもう一度 push してみよう。

git push heroku master

おお。ファイルを push したあともなんだかずらずらと表示されて何かをやっているらしい。なんか TypeError とか出ていて不安な感じだけど、きちんと package.json とかも読んで依存しているパッケージらをインストールしてくれている。

push した後はアプリケーションのプロセスを動かす必要があるみたい。以下のコマンドで起動できるようだ。

heroku ps:scale web=1

起動コマンドを実行したあと、プロセスを確認する。

heroku ps

こんなのが出てきた。

Process  State           Command
-------  --------------  -----------  
web.1    crashed for 4m  node app.js

おや、State のところに crashed とか書いてある。そんなぁ。ログを見てみよう。

heroku logs
~~~ 略 ~~~
2012-02-22T18:21:48+00:00 app[web.1]: Express server listening on port 3000 in development mode
2012-02-22T18:21:49+00:00 heroku[web.1]: Error R11 (Bad bind) -> Process bound to port 3000, should be 56060 (see environment variable PORT)
~~~ 略 ~~~

なんだかこんなのが見えている。これはポート番号の指定がよろしくないのでは。express のひな形だと 3000 決め打ちだったからなぁ。

というわけで、app.coffee の

app.listen 3000

となっていたものを

port = process.env.PORT ? 3000
app.listen port

このようにした。coffeescript で書いているのでこんな感じになった。修正したものを push してやり直してみる。もう一度 heroku ps コマンドで確認する。

Process  State       Command      
-------  ----------  -----------  
web.1    up for 36s  node app.js 

こうなった。よさそう。よかった。

アプリケーションを配置できたので以下のコマンドで公開しよう。

heroku open

コマンドを実行すると、ブラウザで配置したアプリケーションのURLが開かれた。問題なく動いているようだ。

アプリケーションの配置ができましたーこれですー!と言いたいところなのですが、まだ人に見せられるようなところまではできていないので…これからがんばります。まぁ、そのうち。