ExpressとSocket.ioを使ったチャットサンプルを永続化

このエントリはリアルタイムWebハッカソンのハンズオン資料その5です。

今回は、前回のチャットサンプルのチャットログを永続化してみましょう。
node.jsは様々なデータストアと連携することができます。
MySQL, PostgreSQLなどのRDBMSももちろん可能ですが、やはりCouchDB, MongoDB, RedisなどのいわゆるNoSQLと呼ばれるものと連携させるのが人気のようです。
特にJSON形式でそのまま格納することのできるデータストアは、JavaScriptから扱うのに都合がいいというのは言うまでもないと思います。

もちろん、node.js製のデータストアエンジンもいくつかあります。有名なのはnStoreでしょう。
今回はdirtyというライブラリを使います。理由は僕が使ってみたかったからです。

インストールは

$ npm install dirty

で終わり。
……のはずなんだけど、現状(dirty v0.9.0)だと最新のnode v0.2.3で使おうとしたら'constrants'ってモジュールが見つからないよってエラーが出てしまう。
もうパッチはあたっていて、npmにその最新のが登録されていないだけの状態なのでgithubから直接とってくりゃいい。なので

$ cd tmp
$ git clone git://github.com/felixge/node-dirty.git
$ cd node-dirty
$ npm install

でOK

んじゃさっそくdirtyを使ったapp.jsを見てみましょう。変わったのは先頭のrequireの部分

var express = require('express'),
    io = require('socket.io'),
    db = require('dirty')('log.db'),
    json = JSON.stringify;

とsocket.onの引数のfunctionの部分

socket.on('connection', function(client) {
  count++;
  client.broadcast(json({count: count}));
  client.send(json({count: count}));
  db.forEach(function(key, val) {
    client.send(val);
  });

  client.on('message', function(message) {
    // message
    db.set(new Date().getTime(), message);
    client.broadcast(message);
    client.send(message);
  });
  client.on('disconnect', function() {
    // disconnect
    count--;
    client.broadcast(json({count: count}));
  });
});

こんだけです。見ての通り、メッセージを受け取ったらそれを現在時刻のミリ秒をキーにsetしています。
で、新規接続したらそいつに全てのログをforEachで回しながらsendしています。単純ですね。
果たしてこれでどんだけのパフォーマンスが出るかわかりませんが、それはこのチャットを実際に使うハッカソンの会場で判明することでしょう。

リポジトリhttp://github.com/meso/chatsample