Class: Rack::Session::Memcache
- Inherits:
-
Abstract::ID
- Object
- Abstract::ID
- Rack::Session::Memcache
- Defined in:
- lib/rack/session/memcache.rb
Overview
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.
Constant Summary collapse
- DEFAULT_OPTIONS =
Abstract::ID::DEFAULT_OPTIONS.merge \ :namespace => 'rack:session', :memcache_server => 'localhost:11211'
Instance Attribute Summary collapse
-
#mutex ⇒ Object
readonly
Returns the value of attribute mutex.
-
#pool ⇒ Object
readonly
Returns the value of attribute pool.
Attributes inherited from Abstract::ID
Instance Method Summary collapse
- #generate_sid ⇒ Object
- #get_session(env, session_id) ⇒ Object
-
#initialize(app, options = {}) ⇒ Memcache
constructor
A new instance of Memcache.
- #set_session(env, session_id, new_session, options) ⇒ Object
Methods inherited from Abstract::ID
Constructor Details
#initialize(app, options = {}) ⇒ Memcache
Returns a new instance of Memcache.
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/rack/session/memcache.rb', line 28 def initialize(app, ={}) super @mutex = Mutex.new mserv = @default_options[:memcache_server] mopts = @default_options. reject{|k,v| MemCache::DEFAULT_OPTIONS.include? k } @pool = MemCache.new mserv, mopts unless @pool.active? and @pool.servers.any?{|c| c.alive? } raise 'No memcache servers' end end |
Instance Attribute Details
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
23 24 25 |
# File 'lib/rack/session/memcache.rb', line 23 def mutex @mutex end |
#pool ⇒ Object (readonly)
Returns the value of attribute pool.
23 24 25 |
# File 'lib/rack/session/memcache.rb', line 23 def pool @pool end |
Instance Method Details
#generate_sid ⇒ Object
41 42 43 44 45 46 |
# File 'lib/rack/session/memcache.rb', line 41 def generate_sid loop do sid = super break sid unless @pool.get(sid, true) end end |
#get_session(env, session_id) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/rack/session/memcache.rb', line 48 def get_session(env, session_id) @mutex.lock if env['rack.multithread'] unless session_id and session = @pool.get(session_id) session_id, session = generate_sid, {} unless /^STORED/ =~ @pool.add(session_id, session) raise "Session collision on '#{session_id.inspect}'" end end session.instance_variable_set '@old', @pool.get(session_id, true) return [session_id, session] rescue MemCache::MemCacheError, Errno::ECONNREFUSED # MemCache server cannot be contacted warn "#{self} is unable to find memcached server." warn $!.inspect return [ nil, {} ] ensure @mutex.unlock if @mutex.locked? end |
#set_session(env, session_id, new_session, options) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/rack/session/memcache.rb', line 67 def set_session(env, session_id, new_session, ) expiry = [:expire_after] expiry = expiry.nil? ? 0 : expiry + 1 @mutex.lock if env['rack.multithread'] if [:renew] or [:drop] @pool.delete session_id return false if [:drop] session_id = generate_sid @pool.add session_id, {} # so we don't worry about cache miss on #set end session = @pool.get(session_id) || {} old_session = new_session.instance_variable_get '@old' old_session = old_session ? Marshal.load(old_session) : {} unless Hash === old_session and Hash === new_session env['rack.errors']. puts 'Bad old_session or new_session sessions provided.' else # merge sessions # alterations are either update or delete, making as few changes as # possible to prevent possible issues. # removed keys delete = old_session.keys - new_session.keys if $VERBOSE and not delete.empty? env['rack.errors']. puts "//@#{session_id}: delete #{delete*','}" end delete.each{|k| session.delete k } # added or altered keys update = new_session.keys. select{|k| new_session[k] != old_session[k] } if $VERBOSE and not update.empty? env['rack.errors'].puts "//@#{session_id}: update #{update*','}" end update.each{|k| session[k] = new_session[k] } end @pool.set session_id, session, expiry return session_id rescue MemCache::MemCacheError, Errno::ECONNREFUSED # MemCache server cannot be contacted warn "#{self} is unable to find memcached server." warn $!.inspect return false ensure @mutex.unlock if @mutex.locked? end |