OK, I've made all the session management changes that I've been threatening to make and checked them into CVS. Next version of Quixote will probably be 0.5 unless someone finds a small, easy-to-fix, and embarassing bug, in which case we'll roll back the code a bit. I've gotten to the point in the session mgmt docs where I need to talk about persistence, and I have realized that the persistence hooks are biased towards an all-or-nothing approach -- ie. when one session changes, you have to save all of them. This stems from our use of ZODB, because we don't really care if one Session object or 47 of them have changed -- we just call get_transaction().commit() and let ZODB worry about the details. Since this happens at the end of every request, it's guaranteed that only one session will have changed, though. (Modulo multi-threading, which I'm trying to avoid thinking about.) Depending on your application and your persistence mechanism, this could really suck. Eg. you might save sessions by pickling them one at a time to a hash file, or to files in a directory (which would suck with traditional filesystems, but should work pretty well with something like ReiserFS). In those cases, there really ought to be a way to save a single session. So there are a couple of decisions to make. First decision: who should be responsible for session persistence, the session class or the session manager class? I strongly favour the session manager, because only it knows about all sessions and thus it should manage the hash file, or directory, or database connection, or whatever. Anyone disagree? That settled, there's the question of the specific interface. Because we don't want the interface between the publisher and the session manager to be any more complicated than it needs to be, there should be exactly two methods for the publisher to call: one to save the state of the current session, and one to abort any such saving (necessary when using a transactional object database that automagically mirrors changes in objects-in-memory to objects-on-disk, like ZODB). The current interface defined by the standard SessionManager class is dead simple: def abort(self): """ Placeholder for subclasses that implement persistence: abort all changes to all sessions. Called by SessionPublisher when a request fails, ie. when it catches an exception other than PublishError. """ def commit(self): """ Placeholder for subclasses that implement persistence: save all changes to all sessions. Called by SessionPublisher when a request completes successfully, or is interrupted by a PublishError exception. """ I'd like to make two changes here: * fundamentally, this interface should talk about "the current session" rather than all sessions. Both methods should take either a session object or a request object from which the session object can be fetched. Then it's possible to implement save-one- session-at-a-time persistence efficiently. * trivially, I'd like to change the names, which betray a bias towards transactional databases. There's no such requirement here, so I don't think the names should reflect one. Here's the interface I'm leaning towards at the moment: def forget_changes (self, session): """forget_changes(session : Session) Placeholder for subclasses that implement persistence: forget about saving changes to the current session. Called by SessionPublisher when a request fails, ie. when it catches an exception other than PublishError. Probably only useful when your persistence system automatically persists in-memory changes and is transactional (ie. you can use this method to abort the current transaction). """ def save_changes (self, session): """save_changes(session : Session) Placeholder for subclasses that implement persistence: save changes to the current session. Called by SessionPublisher when a request completes successfully, or is interrupted by a PublishError exception. """ How's that grab everyone? Feels pretty right to me. I think I'll code it up and see how hard it is to implement a persistent SessionManager. Greg