finagle-redisを使ったRedisのモックサーバです。
コードはGithub上にあります。
- Redisプロトコル用のFinagle
Codec
- RedisプロトコルをしゃべるFinagleクライアント
- Naggati (後述)
- ユーティリティもろもろ
-
Server
- Finagleサーバを起動させるメインクラス -
service.RedisService
- FinagleService
の実装:def apply(req: SessionAndCommand): Future[Reply] = { // RedisのDBを選択 val db = dbs(req.session.db) req.cmd match { // DBの戻り値(Future[Reply])をそのまま返す case Get(key) => db.get(key) case Set(key, value) => db.set(key, value) // ... 他のコマンド ... } }
-
codec.RedisServerCodec
- finagle-redisのCodecの拡張版 -
filter._
- セッション管理用のFinagleFilter
-
handler.ClientAddressInjector
- セッション管理用のNettyハンドラ -
db._
- Redis DBの実装 (Finagleと無関係)
Redisは接続中のクライアントごとにセッションを立て、下記のような情報を記憶します:
しかしFinagleは基本的にステートレスであり、セッションに対応しません。しかもクライアントのアドレスを知る方法もありません。
そのため、Finagleの裏にあるNettyのパイプラインをいじって次のハンドラを注入します。このハンドラはクライアントのアドレスを抽出してFedisに渡すので、セッション管理は可能になります。
class ClientAddressInjector extends SimpleChannelUpstreamHandler {
override def messageReceived(ctx: ChannelHandlerContext, e: MessageEvent) {
val oldMsg = e.getMessage.asInstanceOf[Command]
val newMsg = CmdFromClient(oldMsg, e.getRemoteAddress)
ctx.sendUpstream(new UpstreamMessageEvent(e.getChannel, newMsg, e.getRemoteAddress))
}
}
Naggatiとは、非同期I/Oを気にせずにNettyチャンネルからデータを復元するための便利なライブラリです。Play 2.0のIterateeと同じような考えで作られています。
Naggatiは別のプロジェクトであるが、なぜかfinagle-redis配下にもコピペされてます。com.twitter.finagle.redis.naggati
パッケージにあります。
Fedisは直接Naggatiを利用しませんが、別のプロジェクトで使ったことがあります。Nettyを扱うのであれば、Naggatiをおすすめします。
ScalaTestのFlatSpecを使っています。Fedisの目的はRedisの仕様を真似ることですから、スペック系のテストはとても向いてます。
時刻関係のテストにcom.twitter.util.Time
を使います。すろとこんな感じでテストを書けます:
withTimeAt(1000L) { _ =>
// ... do something ...
}
withTimeAt(2000L) { _ =>
// ... test assertion ...
}
withCurrentTimeFrozen { _ =>
// ... do something ...
}
Twitterのライブラリに依存するにあたって気をつけなければならないこと:
-
バージョン管理はむちゃくちゃです。最近Twitterが完全に(?)Scala 2.9に移行してだいぶマシになったが、半年前はひどかった.
-
Twitterのプロジェクト間の依存関係についてドキュメントがほとんどありません。何時間も http://maven.twttr.com をブラウズしたり、pom.xmlを読んだり、依存関係と必要なバージョンを推測しました。
-
Twitterの社内GitリポとGithubとの同期は定期的ではなく、「気が向いたら同期する」みたいな感じです。GithubにあるコードはMavenからダウンロードするコードより2、3リリース遅れてることがあります。
Fedisの開発は十分満足したし、誰にも使われてないから、今後あまり時間を費やすつもりはありません。ただ、コマンドをもう少し揃えられたらいいなと思うので、ヒマな時にちょこちょこ手をつけるかもしれません。
Finagleを勉強がてらコマンドを増やしてみたいという方がいれば、もちろんpull requestを歓迎します!