memcache-client と thin の競合 on Ruby1.9.1
TokyoCabinetを使った検索コアは出来上がったのですが、
作るべきはWebシステムなので、それをWeb側から叩かないといけません
しかし、JavaScriptで非同期にリソースを取得する仕組みだと、
そのURIさえわかればデータを自由に取得される恐れがあります
(今回はデータそのものが売り物なので、これだと困る)
リソースURIは正規のユーザが操作している間だけ有効なものですが、
その間に不正にデータを持っていかれる可能性は否定できません
そこで、リソース取得の仕組みに、
独自セッションによる認証を追加することにしました
Rails・・・というよりRackのセッションにこの仕組みを組み合わせ、
画面遷移とリソース取得で、透過的な認証処理を行うようにしたのです(`・ω・´) b
・・・というのが前置きで、ここから本題ですが、
この手のセッション情報の管理にmemcached*1を使うというのは、
最近ではごく一般的な手法だと思います
※以下の話は「ruby1.9.1」環境です
もちろんmemcached込みのRSpecは通過させまして、
Sinatra(0.9.6)で起動するテスト環境に組み込んでみたのですが、
memcachedへ接続するところで、「MemCache::EventedServer」がないと怒られたのです
該当するmemcache-clientのコードを見てみますと、
initializeの以下の部分で落ちてました
self.extend(MemCache::EventedServer) if defined?(EM) and EM.reactor_running?
この「EM」が何かって考えると、おそらく「EventMachine」のことだろうと
(ノンブロックI/Oのあれですね)
なぜEMが定義されたのかわかりませんが、とりあえずrequireを変更
#require 'memcache' require 'memcache/event_machine'
これで「MemCache::EventedServer」が定義されたのですが、
今度は別なエラーがΣ(・ω・ノ)ノ
FiberError - can't yield from root fiber:
該当箇所は「Fiber.yield」しているので、
何かしらやってるんだとは思いますが、
エラーの意味も原因も全くわかりません
しかも、このエラーが出た後、
再度memcachedにアクセスする処理を走らせると、
なぜか正常に通ってしまうのです
さらに同じ処理を走らせると、
今度は「(よくわからない)パラメータがnil」とエラーになってもうお手上げ(´・ω・`)
Fiberを使ってることから、何かサイクル処理がおかしいのかも
ここでしばらく悩んだのですが・・・
考えてみればSinatra(0.9.6)がデフォルトでthin(1.2.7)を起動しており、
thinがeventmachineを使っているのです
おそらく、thinが定義した「EM」とmemcache-clientが競合し、
定義してないクラスを呼んだり、Fiberの処理をおかしくしたと思われます
これを確かめるため、Sinatraを「-s webrick」で起動すると、
見事に想定通りの動きをしました(`・ω・´) b
「require 'memcache'」でも「'memcache/event_machine'」でもOK
最終的に、このテスト環境はPassengerで動かすので、
Passenger(2.2.14)で起動してみると、やっぱり問題なく動きました
つまり、thinとの組み合わせの時だけおかしくなるわけですが、
Sinatra1.0だと修正されてるのでしょうか・・・
試したいところなのですが、Sinatra1.0はerbの処理がうまくいっておらず、
magic-commentつきのerbでも文字コードエラーで落ちてしまうのです
hamlで書いたものは文字コード指定できるので通るのですが・・・
・・・難しいですね(´・ω・`)
*1:あるいは互換インターフェースを持つ分散KVSなど