Play FrameworkのRedis PluginでRedisに突っ込んだオブジェクトを確認する


前回の記事ではPlay FrameworkのRedis Pluginについて簡単に書きました。

今回はこのプラグインについてもう少し書いて行きます。

Redisに格納されたオブジェクトを見る

おそらくほとんどの人が「プラグインで突っ込んだRedis上のオブジェクトを直接見たい!」と思うでしょう。Redisはキャッシュ用途であれ永続化用のDB用途であれ、データストアには代わりありませんので、そりゃ直接見たくなるでしょう。「この処理でRedisに値突っ込むけど、手軽にredis-cli経由で素早く見たい!」みたいな。

では実際に見てみます。

まずは以下のようなコードで適当に値を突っ込んでおきます。

  case class Person(name: String, age: Int)

  def store = Action {
    Cache.set("string-key", "ABCD", 300000)
    Cache.set("int-key", 123, 300000)
    Cache.set("long-key", 123456789L, 300000)
    Cache.set("boolean-key", true, 300000)
    Cache.set("person-key", Person("Taro", 18), 300000)
    Cache.set("person-list-key", List(Person("Taro", 18), Person("Jiro", 17), Person("Saburo", 16)), 300000)
    Cache.set("java-object-key", new IllegalArgumentException("Illegal!!"), 300000)
    Ok("")
  }

適当に色々突っ込んでおいた物を以下の手順で確認します。

# shell上で
redis-cli

keys *

# 以下の様に帰ってきます
1) "person-list-key"
2) "boolean-key"
3) "int-key"
4) "person-key"
5) "long-key"
6) "java-object-key"
7) "string-key"

# 色々キーがあるので、試しにstring-keyの中身を
get string-key

# !?
"oos-rO0ABXQABEFCQ0Q="

string-keyの値としてoos-rO0ABXQABEFCQ0Q=が取れました。

Redis Pluginが格納するオブジェクトについて

上記の例ではstring-keyの値としてoos-rO0ABXQABEFCQ0Q=が取れました。コードでは値ABCDを突っ込んだのに実際は謎の文字列です。

これは何かというとprefixであるoos-と直列化されたデータです。ようするにRedis Pluginで格納したオブジェクトは直列化されているので普通には見れません。

詳しくは以下のコードを見ると良いかと思います。

https://github.com/typesafehub/play-plugins/blob/master/redis/src/main/scala/com/typesafe/plugin/RedisPlugin.scala

どうやってRedis Pluginで格納したデータを見れば良いのか

上記のコードを参考にして全く逆の操作を行うツールを作ろうかな、と思ったのですが、これは現実的ではありません。なぜならデシリアライズするときに対象のクラスの情報が無くてはならないので、スタンドアローンなツールを作ることはできないからです。

という訳で手っ取り早く以下のようなメソッドを作ってしまうのが良いと思います。

適当なコントローラクラスに以下を追記します。

  val pool = new Pool(new JedisPool(new JedisPoolConfig(), "localhost", 6379, 2000))

  def view = Action {
    pool.withJedisClient { client =>

      import scala.collection.JavaConverters._
      val keys: Set[String] = client.keys("*").asScala.toSet

      val sb: StringBuilder = new StringBuilder()

      for (key <- keys) {
        sb.append(s"key = ${key} value = ${Cache.get(key).getOrElse("No Redis Plugin object")}\n")
      }
      Ok(sb.toString)
    }
  }

routeにも追記します。

# メソッド指定部分などは適宜変えてください
GET        /view                controllers.Application.view

この状態で/viewにアクセスすると先ほど格納したデータが以下のように見えます。

key = java-object-key value = java.lang.IllegalArgumentException: Illegal!!
key = string-key value = ABCD
key = person-list-key value = List(Person(Taro,18), Person(Jiro,17), Person(Saburo,16))
key = long-key value = 123456789
key = int-key value = 123
key = person-key value = Person(Taro,18)
key = boolean-key value = true

これでオブジェクトが見れます。

とはいえ、実際に上記のコードをプロダクトコードと一緒にリリースする訳にはいかないので、もう少し工夫が必要ですね。

これについてはいい方法を思いついたらまた書くことにします。