Class: Rack::Session::Memcache

Inherits:
Abstract::ID show all
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

Attributes inherited from Abstract::Persisted

#default_options, #key, #sid_secure

Instance Method Summary collapse

Methods inherited from Abstract::ID

#delete_session, #find_session, inherited, #write_session

Methods inherited from Abstract::Persisted

#call, #commit_session, #context

Constructor Details

#initialize(app, options = {}) ⇒ Memcache


31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rack/session/memcache.rb', line 31

def initialize(app, options = {})
  super

  @mutex = Mutex.new
  mserv = @default_options[:memcache_server]
  mopts = @default_options.reject{|k, v| !MemCache::DEFAULT_OPTIONS.include? k }

  @pool = options[:cache] || MemCache.new(mserv, mopts)
  unless @pool.active? and @pool.servers.any?(&:alive?)
    raise 'No memcache servers'
  end
end

Instance Attribute Details

#mutexObject (readonly)

Returns the value of attribute mutex


25
26
27
# File 'lib/rack/session/memcache.rb', line 25

def mutex
  @mutex
end

#poolObject (readonly)

Returns the value of attribute pool


25
26
27
# File 'lib/rack/session/memcache.rb', line 25

def pool
  @pool
end

Instance Method Details

#destroy_session(env, session_id, options) ⇒ Object


73
74
75
76
77
78
# File 'lib/rack/session/memcache.rb', line 73

def destroy_session(env, session_id, options)
  with_lock(env) do
    @pool.delete(session_id)
    generate_sid unless options[:drop]
  end
end

#generate_sidObject


44
45
46
47
48
49
# File 'lib/rack/session/memcache.rb', line 44

def generate_sid
  loop do
    sid = super
    break sid unless @pool.get(sid, true)
  end
end

#get_session(env, sid) ⇒ Object


51
52
53
54
55
56
57
58
59
60
61
# File 'lib/rack/session/memcache.rb', line 51

def get_session(env, sid)
  with_lock(env) do
    unless sid and session = @pool.get(sid)
      sid, session = generate_sid, {}
      unless /^STORED/ =~ @pool.add(sid, session)
        raise "Session collision on '#{sid.inspect}'"
      end
    end
    [sid, session]
  end
end

#set_session(env, session_id, new_session, options) ⇒ Object


63
64
65
66
67
68
69
70
71
# File 'lib/rack/session/memcache.rb', line 63

def set_session(env, session_id, new_session, options)
  expiry = options[:expire_after]
  expiry = expiry.nil? ? 0 : expiry + 1

  with_lock(env) do
    @pool.set session_id, new_session, expiry
    session_id
  end
end

#with_lock(env) ⇒ Object


80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/rack/session/memcache.rb', line 80

def with_lock(env)
  @mutex.lock if env[RACK_MULTITHREAD]
  yield
rescue MemCache::MemCacheError, Errno::ECONNREFUSED
  if $VERBOSE
    warn "#{self} is unable to find memcached server."
    warn $!.inspect
  end
  raise
ensure
  @mutex.unlock if @mutex.locked?
end