ブログ・ア・ラ・クレーム

技術的なメモとかライフログとか。

Yahoo! JAPAN がオープンソースにした KVS "K2HASH" を mruby スクリプトから利用するための mgem "mruby-k2hash" をつくってみた

この記事は mruby Advent Calendar 2016 26 日目の記事です。・・・というのは嘘です! mruby Advent Calendar 2016 、つつがなく完走しましたね!みなさまお疲れ様でした!

本記事では表題の通り、 mruby-k2hash という mgem を作ってみたことに関する共有になります。

K2HASH とは

K2HASHYahoo! JAPANのブログ でちょろっと紹介されている KVS です。 ソースコードGitHub で閲覧することができます。

上記の記事では簡潔な紹介のみになっていますが、 GitHub の wiki を読む限り下記の点から興味深いプロダクトなような気がします。

こうして列挙してみると、個人的な知識から考えるに Redis に近い機能を保有している気がします。 ただデーモンを立ち上げたりファイルに書き出すことすら必須ではないことから、結構気軽に利用できるように見えます。

mruby-k2hash について

基本方針

今回ご紹介する mruby-k2hash はこの K2HASH への操作を mruby スクリプトから行うことを可能にします。 この mruby-k2hash 、基本的には K2HASH の C インタフェースへの橋渡しをするだけになります。ですがその設計は少し考えた上で行っています。 K2HASH の基本的な機能を目を細めてみると・・・うーん・・・なんだか Ruby の標準ライブラリに存在する DBM に近い気がしてきます。

というわけで mruby-k2hash で実装しているメソッドは DBM が持つものを模倣する 形で行っています。 each も実装していることから Enumerable のメソッドも使えるようになっています。 mruby で dbm の mgem を実装したという例は僕が知る限り無い(あったらコッソリ教えてください!)ので、 mruby-k2hash は mruby で気軽に扱える dbm 代替のひとつ としても利用できるのではないかと考えています。

実際の動作例

mruby-k2hash の実際の動作の例としては下記のようになります。

K2Hash クラスのコンストラクタにファイルパスなどなどを渡すとそのファイルを open しつつインスタンスが生成されます。 fetch, [] メソッドで参照、 store, []= メソッドで更新が行えます。

> k2hash = K2Hash.new('/tmp/tmp.k2hash', 0666, K2Hash::WRCREAT)
 => #<K2Hash:0x127ada0>
> k2hash.store('key', 'value')
 => nil
> k2hash.fetch('key')
 => "value"
> k2hash.store('key', 'new value')
 => nil
> k2hash.fetch('key')
 => "new value"
> k2hash['key2'] = 'value2'
 => "value2"
> k2hash['key2']
 => "value2"
> k2hash.close
 => nil

each メソッドや、それを実装したことによって Enumerable インタフェースのメソッド、例えば map なども利用できます。

> k2hash = K2Hash.new('/tmp/tmp2.k2hash', 0666, K2Hash::WRCREAT)
 => #<K2Hash:0xcef7c0>
> k2hash['key1'] = 'value1'
 => "value1"
> k2hash['key2'] = 'value2'
 => "value2"
> k2hash.each do |k,v|; puts k + ': ' + v; end
key1: value1
key2: value2
 => nil
> k2hash.map do |k,v|; "key is #{k}, value is #{v}"; end
 => ["key is key1, value is value1", "key is key2, value is value2"]

気軽に試す

もろもろビルド済みの Docker image を push してあるので、 pull してご利用ください。

# コンテナ外
$ docker run -i -t syucream/mruby-k2hash /bin/bash

# コンテナ内
root@9cc669af1607:/opt# ./mruby/bin/mirb
mirb - Embeddable Interactive Ruby Shell

> ... # あとはいいかんじにやる

テストとか

ちょっとだけ単体テストを書きました。テストコードを書くに際して IIJ が公開している mruby-mtest を使ってみました。 Travis CI でビルドする際はこの mgem を含めて mruby をビルドし、テストコードを bin/mruby に食わせる形でテストするようにしました。楽でいいですわゾ〜! :D

おわりに

現状の mruby-k2hash は K2HASH の多くの機能(サブキーとかキューとか)を利用できない状態なので、なんとかしたいです。 そのうち気が向いたら機能追加します。