[Web-SIG] Session interface

Chris McDonough chrism at plope.com
Wed Aug 17 07:48:44 CEST 2005

FWIW, some interesting ideas (and not so interesting ideas) for
sessioning architecture in general are captured at




UML that more or less represents Zope's current sessioning model is at:


- C

On Wed, 2005-08-17 at 00:31 -0500, Ian Bicking wrote:
> Mike Orr wrote:
> > Regarding Ian's session interface:
> > http://svn.colorstudy.com/home/ianb/scarecrow_session_interface.py
> > 
> > Ian Bicking wrote:
> > 
> >> Thinking on it more, probably a good place to start would be agreeing 
> >> on specific terminology for the objects involved, since I've seen 
> >> several different sets of terminology, many of which use the same 
> >> words for different ideas:
> >>
> >> Session:
> >>   An instance of this represents one user/browser's session.
> >> SessionStore:
> >>   An instance of this represents the persistence mechanism.  This
> >>   is a functional component, not embodying any policy.
> >> SessionManager:
> >>   This is a container for sessions, and uses a SessionStore.  This
> >>   contains all the policy for loading, saving, locking, expiring
> >>   sessions.
> >>  
> >>
> > 
> > 
> > At minimum, the SessionManager links the SessionStore, Session, and 
> > application together.  It can be generic, along with 
> > loading/saving/locking.  (Although we might allow the application to 
> > choose a locking policy.)  
> That could be a little difficult, since multiple applications may be 
> sharing a session.  But at the same time, applications that don't expect 
> ConflictError are going to be pissed if you configure your system for 
> optimistic locking.
> Of course, given a session ID and a session store, each application 
> could have its own manager.  Possibly.  Hmm... interesting.  In that 
> case each SessionManager needs an id, which is a bit annoying -- it has 
> to be stable and shared, because the same SessionManager has to be 
> identifiable over multiple processes.  But I hate inventing IDs all over 
> the place.  I feel like I'm pulling string keys out of my ass, and if 
> I'm going to pull things out of my ass I at least don't want to then put 
> them into my code.  I sense UUIDs coming on :(
> That said, this isn't the only place I need strings that are unique to 
> an application instance.
> > But expiring is very application-specific, 
> > and it may not be the "application" doing it but a separate cron job.  
> > Perhaps most applications will be happy with an "expire all sessions 
> > unmodified for N minutes", but some will want to inspect the metadata 
> > and others the content.  So maybe all the SessionManager can do is:
> > 
> >    .delete_session(id)   => pass message directly to SessionStore
> >    .iter_sessions()  =>  tuples of (id, metadata)
> >    .iter_sessions_with_content() => tuples of (id, metadata, content)
> I think metadata is probably good; or lazily-loaded sessions or 
> something.  The metadata is important I think, because updating metadata 
> shouldn't be effected by locking and whatnot.  I think Mike mentioned a 
> problem with locking and updating the timestamp contained in the session 
> -- we should avoid that.
> > ... where metadata includes the access time and whatever else we 
> > decide.  Of course, iterating the content may be disk/memory intensive.
> Sure.  We could have a callback to do filtering too, maybe with a 
> default filter by expiration time.  Or event callbacks.
> > If .delete_expired_sessions() is included, the application would have to 
> > subclass SessionManager rather than just using it.  That's not 
> > necessarily bad but a potential limitation.  Or the application could 
> > kludge up a policy from your methods:
> > 
> >    cutoff = time.time() - (60 * 60 * 4)
> >    for sid in sm.session_ids():
> >        if sm.last_accessed(sid) < cutoff:
> >            sm.delete_session(sid)
> > 
> > I suppose kludgy is in the eye of the beholder.  This would not be kludgy:
> > 
> >    cutoff = time.time() - (60 * 60 * 4)
> >    for sid, metadata in sm.iter_sessions():
> >        if metadata.atime < cutoff:
> >            sm.delete_session(sid)
> > 
> > Curses on anybody who says, "What's the difference?"
> > 
> > PS. Kudos for using .names_with_underscores rather than .studlyCaps.
> > 
> > Your other methods look all right at first glance.  We'll know when we 
> > port existing frameworks to it whether it's adequate.  (Or should that 
> > be "when we port it to existing frameworks"?  Or "when we make existing 
> > frameworks use it as middleware"?)  We'll also have to keep an eye on a 
> > usage pattern to recommend for future frameworks, and on whether this 
> > API has anything to do with the "sessionless" persistance patterns that 
> > have also been proposed.
> Acquiring or creating a session ID is outside of the scope of this 
> interface, but I think that's much of what would be useful to 
> sessionless users.  Or, rather, people who want application-specific 
> sessions.
> > Interesting ideas you've had about read/write vs read-only sessions.  
> > I'd say let's support read-only sessions, and maybe that will encourage 
> > applications to use them.
> > 
> > Session ID cookies seem like a generic thing this class should handle, 
> > especially for applications that don't otherwise use cookies.  XML-RPC 
> > encapsulates the XML (an necessary evil); why shouldn't we encapsulate 
> > the cookie (another necessary evil)?
> XML-RPC contains the XML, but it doesn't deal with the transport really. 
>   And, just using XML-RPC as an example, what if you want to stuff the 
> session ID inside the XML-RPC request instead of in a cookie header?
> But anyway, the reason I don't want to handle this is because this would 
> be much easier if building upon a Standard That Does Not Yet Exist, and 
> I'd rather avoid overlapping with that standard.
> >> Does that sound good?  Note that the attached interface conflates 
> >> SessionStore and SessionManager.  Some interfaces make an explicit 
> >> ApplicationSession, which is contained by Session and keyed off some 
> >> application ID; my interface implies that separation, but does not 
> >> enforce it, and does not offer any extra functionality at that level 
> >> (e.g., per-ApplicationSession locks or transactions).
> >>  
> >>
> > 
> > 
> > I'm not sure what you mean by ApplicationSession.  Perl's session object 
> > is a dictionary, and you can store anything in it.  Our top-level object 
> > has to be flexible due to grandfathering, unless we want to force 
> > applications to translate to/from our session object to their native 
> > session format.  Yet you define certain attributes/methods the Session 
> > must have, which legacy Sessions don't.  I guess allow the application 
> > to provide a subclass or compatible class, and let it worry about how to 
> > upgrade its native session object.
> I was thinking of pythonweb's "Store": 
> http://pythonweb.org/projects/webmodules/doc/0.5.3/html_multipage/lib/node153.html
> I vaguely suggest in the interface that each application should put all 
> of its data in a single key (based on the application name).  Now I 
> think that should be based on a unique name (not the application name, 
> because the application may exist multiple times in the process), and 
> maybe with an entirely different manager.
> > Regarding sessionless persistence, that reminds me of a disagreement I 
> > had with Titus in designing session2.  Quixote provides Session.user 
> > default None, but doesn't define what other values it can have.  I put a 
> > full-fledged User object with username/group/permission info.  Titus 
> > puts a string name and stores everything else in his application 
> > database.  So his *SessionStore classes put the name in a VARCHAR column 
> > and didn't save the rest of the session data.  I argued that "most 
> > people will have a User object, and they'll expect the entire Session to 
> > be pickled because that's what PHP/Perl do."  He relented, so the 
> > current *SessionStores can be used either way.
> In the interface I suggest anything pickleable can go in a key.  This 
> requirement has been the source of some controversy in Webware, since 
> people wanted to put open file objects and such in the session; mostly 
> people coming from Java where apparently that's the norm.  Anyway, it's 
> still possible with this interface to have a store that never pickles 
> anything; I can just hope no one writes code they expect anyone else to 
> use that demands in-memory session storage.  Those are lame even when 
> you are using threads.
> I think the example shows one reason the session shouldn't be considered 
> a public API.  I think it's fine to put the username or the user object 
> in the session -- we can debate the pluses and minuses, but it works -- 
> but I think you should definitely wrap that implementation detail in 
> something else.  E.g., request.user should return 
> request.session['user'] or something.
> > Perhaps applications should store all session data directly, keyed by 
> > session ID (and perhaps "username"), rather than using pickled 
> > Sessions.  That would be a good idea for a parallel project.  I'm not 
> > sure how relevant that would be to this API except to share "cookie 
> > code".  This API + implementations are required in any case, both 
> > because "most users" will not consider Python if it doesn't have "robust 
> > session handling", and a common library would allow frameworks to use it 
> > rather than reinventing the wheel incompatibly.  This is true regardless 
> > of the merits of sessions.
> I guess if applications each have their own SessionManager, they could 
> have their own Session classes, and if they wanted to the Session 
> objects could use application-specific storage and even an 
> application-specific API (not just a dictionary interface).  I don't 
> know what the point of that would be, though, since it's all 
> application-specific and not generic, so you might as well just use the 
> session ID and ignore the rest of the API.

More information about the Web-SIG mailing list