drubyで作る超適当なRackセッション
Rack::Session::Memcacheを参考にdrubyで同じようなことをやってみたら、意外と簡単にできてしまった。
あとは、セッション管理側に適切な排他制御を実装すれば、それなりに使えるかな。
セッションを保持するdrubyサーバ
drb_session_manager.rb:
require 'drb' class DRbSessionManager attr_reader :pool def initialize @pool = {} end def set(session_id, session) @pool[session_id] = session end def get(session_id) @pool[session_id] end end DRb.start_service('druby://localhost:11211', DRbSessionManager.new) sleep
drubyサーバにアクセスするRackのセッション
drbpool.rb:
require 'rack/session/abstract/id' require 'drb' module Rack module Session class DRbPool < Abstract::ID attr_reader :pool DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge \ :namespace => 'rack:session', :druby_server => 'druby://localhost:11211' def initialize(app, options={}) super @pool = DRbObject.new_with_uri(@default_options[:druby_server]) end def generate_sid loop do sid = super break sid unless @pool.get(sid) end end def get_session(env, session_id) unless session_id and session = @pool.get(session_id) session_id, session = generate_sid, {} @pool.set(session_id, session) end return [session_id, session] end def set_session(env, session_id, new_session, options) @pool.set(session_id, new_session) return session_id end end end end
sinatraを使ってセッションのテスト
main.rb:
require 'sinatra' require './drbpool' use Rack::Session::DRbPool get('/') do session[:count] = (session[:count] || 0) + 1 "count: #{session[:count]}" end
実行してみる。
hiro@neptune% ruby drb_session_manager.rb & [1] 4144 hiro@neptune% ruby main.rb == Sinatra/1.1.2 has taken the stage on 4567 for development with backup from Thin >> Thin web server (v1.2.7 codename No Hup) >> Maximum connections set to 1024 >> Listening on 0.0.0.0:4567, CTRL+C to stop
別ターミナルで。
hiro@neptune% curl --cookie-jar cookie.txt http://localhost:4567 count: 1 hiro@neptune% cat cookie.txt # Netscape HTTP Cookie File # http://curl.haxx.se/rfc/cookie_spec.html # This file was generated by libcurl! Edit at your own risk. #HttpOnly_localhost FALSE / FALSE 0 rack.session d0673073b2f257040f22a0757d3e67f8 hiro@neptune% curl --cookie rack.session=d0673073b2f257040f22a0757d3e67f8 http://localhost:4567 count: 2 hiro@neptune% curl --cookie rack.session=d0673073b2f257040f22a0757d3e67f8 http://localhost:4567 count: 3
DRbSessionManagerの中身を確認してみる。
hiro@neptune% irb irb(main):001:0> require 'drb' => true irb(main):002:0> d = DRbObject.new_with_uri('druby://localhost:11211') => #<DRbSessionManager:0x10164bc0> irb(main):003:0> d.pool => {"d0673073b2f257040f22a0757d3e67f8"=>{:count=>3}} irb(main):004:0>