Below is quick implementation of this proposal. First we need to patch
up Beaker's Session object to record it's "dirty" state(has been
modified), and to allow clients to check the "accessed" and "dirty"
properties:
beaker_patch.py
===============
import beaker.session
def __setitem__(self, key, value):
self.__dict__['_dirty'] = True
self._session()[key] = value
def __delitem__(self, key):
self.__dict__['_dirty'] = True
self._session().__delitem__(key)
def save(self):
self._session().save()
self.__dict__['_dirty'] = False
def accessed():
return self.__dict__['_sess'] is not None
def dirty(self):
return self.__dict__.get('_dirty') is not None
beaker.session.SessionObject.__setitem__ = __setitem__
beaker.session.SessionObject.__delitem__ = __delitem__
beaker.session.SessionObject.save = save
beaker.session.SessionObject.accessed = accessed
beaker.session.SessionObject.dirty = dirty
Now we need to implement the autosave in a custom middleware, which
checks the config file for a "beaker.session.autosave" setting
(defaults to "off").
autosave_opt_val = ('off', 'if_accessed', 'on')
class CustomMiddleware(object):
def __init__(self, application, config):
self.application = application
self.opt_val = 0
opt_name = 'beaker.session.autosave'
if opt_name in config:
for idx, name in enumerate(autosave_opt_val):
if config[opt_name] == name:
self.opt_val = idx
break;
else:
raise Exception('Invalid option %r for %r in config
file' %
(config[opt_name], opt_name))
def __call__(self, environ, start_response):
content = self.application(environ, start_response)
if (self.opt_val==2 and session.dirty()) or
(self.opt_val==1 and session.accessed()):
session.save()
return content
Now you can enable autosave in development.ini:
beaker.session.autosave = on
So you can now go ahead and remove all the session.save() calls in
your controllers and templates. The seesion will be save if and only
if it has been modified, that is if an attribute was assigned or
deleted.
On Jan 6, 8:35 pm, Tycon <[email protected]> wrote:
> The session object is a very useful feature of pylons and is core to
> any web application. In pylons the session objects acts like a
> dictionary that you can access and modify, as well as save it to a
> storage manager which can be memory, file, dbms, memcached, etc.
> Normally you want to save whatever changes you made to the session
> object, so you have to explictly call session.save(). The most logical
> place to do that is at the end of processing a request, but it's
> annoying to do that at the end of every request and other wrappers
> can't easily tell if the session was modified and needs to be saved.
> Since the session can be modified by different parts of your code
> during a request, and you are not always sure if those changes will be
> saved at the end, what ends up happening is that the session is saved
> multiple times during one request, which is wasteful.
>
> Therefore, I have a suggestion to have a "session.autosave" setting in
> the config file that will have the following options:
>
> off: don't autosave
> on: save the session object at the end of the request, if it was
> modified during the request
> if_accessed: saves the session object at the end of the request, if
> it was accessed during the request
> compat: saves the session object when it's first accessed during the
> request, updating the _accessed_time attribute.
>
> The difference between "if_accessed" and "on" options is that for
> "if_accessed" the session is saved at the end of the request if it was
> accessed or modified, but for "on" options it's only saved if it was
> modified. In either case this means you can remove all the explicit
> "session.save()" statements from your code. Applications that don't
> care about the "_accessed_time" attribute can use the "on" setting so
> the session will be saved only if you actually modified it (this will
> produce better performance).
>
> The last option ("compat") sounds kind of silly, but it's actually the
> way the session object currently works: the first time you try to
> access the session object, it is loaded using the storage manager, the
> "_accessed_time" attribute is updated to now, and then the session is
> immediately saved back. So any subsequent changes you make to the
> session object need to be saved explicitly. The new option "if
> accessed" gives you almost the exact same behavior by making sure the
> session is saved if it was accessed, but since it saves at the end of
> the request - the session is only saved once (and you don't need to do
> it explicitly anymore).
>
> A related note to all those automatic "_something_time" attributes -
> there is a bug with "creation_time" that it gets set to "now" when you
> do a session.save(). It will be better to have a "_modified_time"
> attribute that records when the session was changed, but leave the
> original "_creation_time" unchanged so it reflects the original
> creation time.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---