Below is a working memcache session store class. You can use it by
setting beaker.session.namespace_class in the config file
(development.ini), for example:
beaker.session.namespace_class = myproject.ext.SessionStore
beaker.session.url = 127.0.0.1:11211
beaker.session.ttl = 60
The ttl parameter is expiration timeout, as I'm not sure exactly how
to use/pass the expires/expiration parameter which already exists in
the beaker NamespaceManager.
ext.py:
-----------------------------------------------------------
from beaker.container import NamespaceManager
from beaker.exceptions import InvalidCacheBackendError,
MissingCacheParameter
from beaker.synchronization import file_synchronizer,
null_synchronizer
from beaker.util import verify_directory, SyncDict
import memcache
class SessionStore(NamespaceManager):
clients = SyncDict()
def __init__(self, namespace, url=None, data_dir=None,
lock_dir=None, ttl=604800, **params):
NamespaceManager.__init__(self, namespace)
if not url:
raise MissingCacheParameter("url is required")
if lock_dir is not None:
self.lock_dir = lock_dir
elif data_dir is None:
raise MissingCacheParameter("data_dir or lock_dir is
required")
else:
self.lock_dir = data_dir + "/container_mcd_lock"
verify_directory(self.lock_dir)
self.mc = SessionStore.clients.get(url,
memcache.Client, url.split(';'), debug=0)
self.ttl = int(ttl)
self.hash = {}
def get_access_lock(self):
return null_synchronizer()
def get_creation_lock(self, key):
return file_synchronizer(
identifier="memcachedcontainer/funclock/%s" %
self.namespace,lock_dir = self.lock_dir)
def open(self, *args, **params):
self.hash = self.mc.get(self.namespace) or {}
def close(self, *args, **params):
if not self.mc.set(self.namespace, self.hash, self.ttl):
raise InvalidCacheBackendError("Cannot connect to
Memcached server")
self.hash = {}
def __getitem__(self, key):
return self.hash[key]
def __contains__(self, key):
return self.hash.has_key(key)
def __setitem__(self, key, value):
self.hash[key] = value
def __delitem__(self, key):
del self.hash[key]
def do_remove(self):
self.mc.delete(self.namespace)
self.hash = {}
def keys(self):
return self.hash.keys()
On Dec 30, 8:22 pm, Michael Bayer <[email protected]> wrote:
> On Dec 30, 6:09 pm, Tycon <[email protected]> wrote:
>
>
>
> > Let me clarify that using memcached in beaker doesn't work ONLY FOR
> > STORING SESSIONS.
>
> > It does work for regular caching in beaker (e.g. using @beaker_cache
> > decorator
> > to cache controller actions etc).
>
> > This is not a bug, it's basically an incorrect implementation, which
> > uses wrong design and is completely untested. For storing sessions in
> > mecached you need to do the same thing as when storing session in a
> > file - pickle the session and store it as a single key in memcached.
> > So you can update or remove the session object in a single mecached
> > call, and all the sessions attributes will have the same expiration.
> > Storing each session attribute as a separate record is incorrect
> > because memcached doesn't allow you to update/iterate/delete groups of
> > records together.
>
> I'd like to add that the current incorrect memcached/Session
> implementation is preferable to the previous implementation, in that
> it fails immediately. The old version *would* appear to work since it
> would store an additional element in memcached which consisted of all
> the keys for a particular namespace, thereby allowing namespace.keys()
> to work. But if the cache started pruning its data, then you'd get
> random holes in your session data, or perhaps the list of keys() would
> be pruned causing a similar failure to the one you have...but only
> after many hours/days of uptime.
>
> That the file-based storage stores the session as a pickled dictionary
> is an implementation detail of that backend. So once the Session is
> modified to be appropriate against memcached, it would store a single
> key in a session-id corresponding namespace, containing the session
> dictionary (the Python memcached API does the pickling for us). Its
> important that the namespace name is associated with the session id,
> as opposed to using a constant namespace for all sessions - since in
> file-based land, the namespace corresponds to a single file, and it
> wouldn't perform very well to have all user sessions stored in a
> single giant file with a single pickled dict inside.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"pylons-discuss" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---