Ian Bicking wrote: >Same location: > >http://svn.colorstudy.com/home/ianb/scarecrow_session_interface.py > >
Good work. >This version separates out SessionManager from SessionStore, and >suggests that managers be per-application (or maybe per-framework). > There's per-application/per-framework at the class level and instance level; I'm not sure which you're referring to. Regarding the former, I was saying we may be able to make a generic SessionManager class usable as-is by several frameworks. You seemed to doubt this, but I argued we should at least try. The latter only matters in multi-application deployments, where several applications (possibly different frameworks) are sharing a session. Several features below seem to exist only for this environment, and I'm having a hard time evaluating them without knowing the complete use cases you're trying to support. You've said bits about that but maybe we can flesh it out. * Scenario 1: Two apps mounted at /foo and /bar, using a common Paste dispatcher. Both applications are embedded in the same process. (threaded or asynchronous servers) * Scenario 2: Same, but the apps are in separate processes. The dispatcher remains. (forking servers) * Scenario 3: Two apps mounted at /foo and /bar, using separate handlers in the Apache config. At no point is there a common Python process between them. * Scenario 4: Two apps in different virtual hosts. * Scenario 5: Two apps in different webservers. * Others: ?? Which situations are you trying to support, which session-related objects would there be, and how would they interrelate? At what point do we say scenarios won't attract enough users to justify our time? I'm also not sure how these would relate to your "application inversion" paradigm. I'm used to applications as single long-running units that can hold shared state. But your Paste implementation seems to suggest instantiating the application for each URL, and maybe the application would last for only one request. I'm not sure how easy that will be to port some applications to it, or how this impacts the session classees/instances. >class SessionError(Exception): > pass > >class InvalidSession(SessionError): > """ > Raised when an invalid session ID is used. > """ > >class SessionNotFound(SessionError, LookupError): > """ > Raised when a session can't be found. > """ > >class ConflictError(SessionError): > """ > Raised when the ``locking_policy`` is ``optimistic``, and a > session being saved is stale. > """ > >def create_session_id(): > > Could go into a SessionCookie class, along with anything else that can be used by both session-based and sessionless fans. >class ISessionListener: > > Is this just an extra, or what are listeners for? Is this for per-application behavior with a shared manager? >class ISessionManager: > > id = """The string-identifier for this session manager. > > All applications that share this session manager need to use the > same id when creating the session manager. > > With this rule I was expecting some central repository of session managers, and factory functions a la logger.getLogger(), but there doesn't seem to be any. What's the purpose of the SessionManager id? > locking_policy = """The lock policy. > > This is one of these strings: > > ``'optimistic'``: > Optimistic locking; concurrent sessions may be opened for writing; > however, if a session is saved that was loaded before the last save > of the session, a ConflictError will be raised. > > ``'lossy'``: > First-come-first-serve. No locking is done; if a session is written > it overwrites any other session data that was written. > > ``'serialized`'': > All sessions opened for writing are serialized; the request is > blocked until session is available to be opened. > """ > > Optimistic locking sounds like a pain. The application would have to catch the error and then... what? Say "Sorry, your form input was thrown away." Redo the operation somehow (isn't that the same as lossy operation?). Reconcile the two states somehow (how?)? Not that we shouldn't provide it, just that it will need more howto documentation. > def delete_expired_sessions(): > """Scan for and delete any expired sessions. > > ???: How are sessions defined to be expired? Should listeners > participate? Should they be able to cancel an expiration? > """ > > def session_ids(): > """Return a list of session IDs. > > ???: Should this return other metadata, like last accessed > time? > """ > > If so, it shouldn't be called .session_ids(). >class ISession: > > manager = """Reference to parent ISessionManager object""" > > def __init__(id, manager, read_only, last_accessed, creation_time, >data): > """Create the session object > > def touch(): > """Update the session's last_accessed time. > > Typically just calls ``self.manager.touch(self.id)`` > """ > > def commit(): > """Calls ``self.manager.save_session(self)`` > """ > > def rollback(): > """Calls ``self.manager.unlock_session(self)``. > > Also calls ``session_listener.rollback(self)``. > """ > > These look like they don't belong here. The application already has a reference to the SessionManager and should call it directly. It points up a difference in philosophy between the session being a "dumb object" (no reference to the manager) vs being manager-aware. Is the latter necessary? Are you thinking of cases where the session would be provided by the middleware, then the application would have dispose of the session at the end of the request? The middleware could provide a reference to the session manager for this. Although that would expose irrelevant methods. > class ISessionStore: > def load_session(session_store_id, session_id, read_only, > session_factory): > def session_ids(session_store_id): > def delete_session(session_store_id, session_id): > def touch(session_store_id, session_id): > def write_lock_session(session_store_id, session_id): Isn't session_store_id 'self'? Specifying it seems to imply this is a meta SessionStore, not an individual store. Why would a deployment have multiple stores? _______________________________________________ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com