Seiichi Yonezawa — How creativity is helped by failure

Kueを使って悪夢をみる(明晰夢?)

ここ数日はサイバーマンデーでガッツリ買い物してしまった私です。それはそうと、ここ数日のサイドプロジェクトのつもりでHTTPサーバでRhythmboxを動かすということを試していました。これがそこそこ動いてくれるようになったので、以前習得したDockerと合わせて今回はNode.JSでNightmare.jsを手元ではなく、ついにヘッドレスで動かしてみようと思いました。

Nightmare.jsは面白いですね。これをさわればさわるほどJavaScriptが使えてよかったと実感します。でも、あくまでコマンドを実行するタイミングは私がTerminalに特定のコマンドを打つ時だけ。それをブラウザ経由でできたら素晴らしいと思いませんか。私はそう思います。寝転がってる時でもいいし、外出したり、寝てる間にタスクを実行してくれるはずです。もちろんサーバーが動いているのは前提ですが。まあ、その気になればDockerさえ動かせればAWS経由でもApp Engineでもなんだっていいわけです。

ずいぶんと夢のある話ですね!そこで、RubyではSidekiqというgemがありますが、Node.jsの世界では今の所Kueというプロジェクトが最も人気があるようです。AutomatticといえばWordPressもそうですが、Socket.IOもAutomattic製。でもよーくコミットログを遡ってみるとTJの文字が。というか、もうほとんどTJが作ったプロジェクトのようですね。ありがとうTJ Holowaychuk。

さて、そのサンプルのvideo.jsというものを見てみましょう。

function create() {
  var name = [ 'tobi', 'loki', 'jane', 'manny' ][ Math.random() * 4 | 0 ];
  console.log( '- creating job for %s', name );
  jobs.create( 'video conversion', {
    title: 'converting ' + name + '\'s to avi', user: 1, frames: 200
  } ).save();
  setTimeout( create, Math.random() * 3000 | 0 );
}

create();

この箇所は4人のユーザがそれぞれAVI形式のファイルをだいたい3秒感覚でエンコードしている挙動をシミュレートしています。

jobs.process( 'video conversion', 3, function ( job, done ) {
  var frames = job.data.frames;
  console.log( "job process %d", job.id );
  function next( i ) {
    // pretend we are doing some work
    convertFrame( i, function ( err ) {
      if ( err ) return done( err );
      // report progress, i/frames complete
      job.progress( i, frames );
      if ( i == frames ) done()
      else next( i + 1 );
    } );
  }

  next( 0 );
} );

function convertFrame( i, fn ) {
  setTimeout( fn, Math.random() * 100 );
}

ここではエンコーディングの挙動として再帰が使われていますが、注目すべきはjob.progressの箇所です。実際のコードでは必ずしも現在の進捗が表示できるとも限らないのですが、ここの部分を作業中に更新してあげればちゃんとジョブがきちんと実行されてるか監視できますね。
そしてジョブが完了した時に引数のdone()を実行すればよいのでしょう。

var app = express()
app.use(kue.app)
app.listen(3000)
console.log('UI started on port 3000')

本来はBASIC認証が使えてたはずなのですが、Expressのバージョンが古かったらしく若干書き換えました。しかし、簡易的ですがUIがあらかじめ用意されているおかげでUI部分は特に用意しなくても最悪これだけでうまくいきそう。というわけで続き書いてきます!