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


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

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


23
24
25
# File 'lib/rack/session/memcache.rb', line 23

def mutex
  @mutex
end

#poolObject (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

#destroy_session(env, session_id, options) ⇒ Object


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

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

#generate_sidObject


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

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

#get_session(env, sid) ⇒ Object


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

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


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

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


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

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