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

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

KVS をゆるくつなぐ mrbgem "mruby-neco" を作ってみた

あけましておめでとうございます。正月は実家に帰省してネコと戯れて過ごしました。

新年一発目の記事は、新しく作成した mrbgem "mruby-neco" を紹介してみます。

mruby-neco について

mruby-neco は NoSQL Elastic Command Organizer の略としています。はい、言いたかっただけな名前です。

さて mruby-neco ですが、あまた在る NoSQL 、というか特に KVS について、 mruby スクリプト向けにひとまとめしたインタフェースを提供するものです。 具体的には現状下記プロダクトをサポートしています

これらのプロダクトに対して、下記のインタフェースを提供します。

  • get
    • key に対する value を取得する
  • put ,
    • key に対する value を保存する
  • delete
    • key, value のペアを削除する
  • each
    • key, value のペアを受け取るブロックを回すイテレータ
    • Enumerable を include してるので map とか filter とか reduce も使える

それぞれの操作に対して、特定プロダクトを対象にするか、いくつかのプロダクトをひとまとめにした集合を対象にするかを選択できるようにしています

モチベーション

mruby-neco を作ったモチベーションですが、以前の記事で mruby-k2hash というmrbgem を実装した際に、他の KVS から値を持ってきていろいろできてもいいなぁと思ったのと、各プロダクトに付与されている場合がある cli ツールの操作感に差異があり、それを埋める手段が欲しいなぁと思った次第です。 既存の手段でその望みはかなえられる気がしないでもないですが、ここは mruby マンとして mruby でいい感じに KVS 間のデータのやり取りや加工をできると面白いのでは・・・と考えサクッと実装してみました。 ちまたに mrbgem も充実していて、苦労せず実装に踏み出せると考えたという背景もあります。

実際の mruby-neco 利用例

mruby-neco を利用して値を参照更新する例を掲載してみます Org という構造にメンバーを追加し、 Org を介して操作する、みたいな構造を取っています。 Org と各プロダクトのドライバ間の際は Adapter クラスで吸収する形になります。

org = Neco::KvsOrg.new

org.add_member(:etcd, {:url => 'http://127.0.0.1:2379/v2'})
org.add_member(:lmdb, {:path => '/tmp/tmp.lmdb', :options => {:flags => MDB::NOSUBDIR}})
org.add_member(:redis, {:host => 'localhost', :port => 6379})
org.add_member(:k2hash, {:path => '/tmp/tmp.k2hash', :options => {:mode => 0666, :flags => K2Hash::NEWDB}})

org.put_to :etcd, 'key', 'etcd'
org.put_to :lmdb, 'key', 'lmdb'
org.put_to :redis, 'key', 'redis'
org.put_to :k2hash, 'key', 'k2hash'
p org.get_from_all 'key' #=> {:redis=>"redis"}

org.put_to_all 'key', 'value'
p org.get_from_all 'key' #=> {:etcd=>"value", :lmdb=>"value", :redis=>"value", :k2hash=>"value"}

puts 'each_for :redis'
org.each_for(:redis) do |key, value|
  puts "key: #{key}, value: #{value}"
end

puts 'each'
org.each do |key, value|
  puts "key: #{key}, value: #{value}"
end

コマンドラインから neco を利用する

ダンな mruby マンとしては mruby-cli も使ってみたいよね・・・というわけで、 neco-cli という、上記の get と put 操作をコマンドラインから行えるツールを作ってみました。 下記のような使用感になります。

$ neco-cli help
  usage: neco-cli <subcmd>
         neco-cli get <key> [--open <db options as JSON>]
         neco-cli put <key> <value> [--open <db options as JSON>]

  example: neco-cli set "key1" "value1" --open '{"name": redis, "addr": "127.0.0.1", "port": 6379}'

$ neco-cli put key hoge --open '{"name": "redis", "host": "127.0.0.1", "port": 6379}'
$ neco-cli get key --open '{"name": "redis", "host": "127.0.0.1", "port": 6379}'
{"redis":"hoge"}

$ neco-cli put key fuga --open '{"name": "redis", "host": "127.0.0.1", "port": 6379}' --open '{"name": "etcd", "url": "http://127.0.0.1:2379/v2"}'
$ neco-cli get key --open '{"name": "redis", "host": "127.0.0.1", "port": 6379}' --open '{"name": "etcd", "url": "http://127.0.0.1:2379/v2"}'
{"redis":"fuga","etcd":"fuga"}

open オプションの内容と get で得た値のフォーマットは現状 JSON としています。

ネコについて

冒頭で触れた実家のネコですが、 4 ヶ月ほど顔を合わせてなかったにも関わらず僕のことを覚えているようで、全力で甘えに来てくれました(かわいい) しかしながらネコの中で何らかのポリシーがあるのか、あちらから触れてくることは多々あるのですが、こちらから頭を撫でるなど触れるとコレジャナイ感を覚えているような顔をして去っていってしまいます(かなしい)