[Web-SIG] Session interface
Mike Orr
mso at oz.net
Wed Aug 17 06:54:48 CEST 2005
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.) 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)
... where metadata includes the access time and whatever else we
decide. Of course, iterating the content may be disk/memory intensive.
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.
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)?
>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.
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.
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.
-- Mike Orr <mso at oz.net>
More information about the Web-SIG
mailing list