Abstract::ID
Rack::Session::Memcache provides simple cookie based session management. Session data is stored in memcached. The corresponding session key is maintained in the cookie. You may treat Session::Memcache as you would Session::Pool with the following caveats.
Setting :expire_after to 0 would note to the Memcache server to hang onto the session data until it would drop it according to it’s own specifications. However, the cookie sent to the client would expire immediately.
Note that memcache does drop data before it may be listed to expire. For a full description of behaviour, please see memcache’s documentation.
# File lib/rack/session/memcache.rb, line 28
28: def initialize(app, options={})
29: super
30:
31: @mutex = Mutex.new
32: mserv = @default_options[:memcache_server]
33: mopts = @default_options.
34: reject{|k,v| !MemCache::DEFAULT_OPTIONS.include? k }
35: @pool = MemCache.new mserv, mopts
36: unless @pool.active? and @pool.servers.any?{|c| c.alive? }
37: raise 'No memcache servers'
38: end
39: end
# File lib/rack/session/memcache.rb, line 41
41: def generate_sid
42: loop do
43: sid = super
44: break sid unless @pool.get(sid, true)
45: end
46: end
# File lib/rack/session/memcache.rb, line 48
48: def get_session(env, session_id)
49: @mutex.lock if env['rack.multithread']
50: unless session_id and session = @pool.get(session_id)
51: session_id, session = generate_sid, {}
52: unless /^STORED/ =~ @pool.add(session_id, session)
53: raise "Session collision on '#{session_id.inspect}'"
54: end
55: end
56: session.instance_variable_set '@old', @pool.get(session_id, true)
57: return [session_id, session]
58: rescue MemCache::MemCacheError, Errno::ECONNREFUSED
59: # MemCache server cannot be contacted
60: warn "#{self} is unable to find memcached server."
61: warn $!.inspect
62: return [ nil, {} ]
63: ensure
64: @mutex.unlock if @mutex.locked?
65: end
# File lib/rack/session/memcache.rb, line 67
67: def set_session(env, session_id, new_session, options)
68: expiry = options[:expire_after]
69: expiry = expiry.nil? ? 0 : expiry + 1
70:
71: @mutex.lock if env['rack.multithread']
72: if options[:renew] or options[:drop]
73: @pool.delete session_id
74: return false if options[:drop]
75: session_id = generate_sid
76: @pool.add session_id, {} # so we don't worry about cache miss on #set
77: end
78:
79: session = @pool.get(session_id) || {}
80: old_session = new_session.instance_variable_get '@old'
81: old_session = old_session ? Marshal.load(old_session) : {}
82:
83: unless Hash === old_session and Hash === new_session
84: env['rack.errors'].
85: puts 'Bad old_session or new_session sessions provided.'
86: else # merge sessions
87: # alterations are either update or delete, making as few changes as
88: # possible to prevent possible issues.
89:
90: # removed keys
91: delete = old_session.keys - new_session.keys
92: if $VERBOSE and not delete.empty?
93: env['rack.errors'].
94: puts "//@#{session_id}: delete #{delete*','}"
95: end
96: delete.each{|k| session.delete k }
97:
98: # added or altered keys
99: update = new_session.keys.
100: select{|k| new_session[k] != old_session[k] }
101: if $VERBOSE and not update.empty?
102: env['rack.errors'].puts "//@#{session_id}: update #{update*','}"
103: end
104: update.each{|k| session[k] = new_session[k] }
105: end
106:
107: @pool.set session_id, session, expiry
108: return session_id
109: rescue MemCache::MemCacheError, Errno::ECONNREFUSED
110: # MemCache server cannot be contacted
111: warn "#{self} is unable to find memcached server."
112: warn $!.inspect
113: return false
114: ensure
115: @mutex.unlock if @mutex.locked?
116: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.