Hey Laurence,

[cc-ed Mike in case he hadn't seen this thread and has comments]

Thanks for the continued back and forth; I'm learning about SQLAlchemy and hopefully my pushing helps you improve your ideas too.

Laurence Rowe wrote:
Martijn Faassen wrote:
[using scoped sessions]
That would be fine if you had the same configuration across all sessions (e.g. they all connected to the same engine / database) or each session was configured at the start of every request. Presumably we will want to connect different application instances to different databases.

Mike Bayer suggested configuring the session with the proper engine at the start of each request in his example that I quote at the start of the thread. How expensive actually is it to configure a session with an engine? I'm still getting back to combining scoped sessions and utilities, though.

We need to do two things:

* convince scoped session to return the session appropriate for our application. We can do this by introducing a custom scopefunc that takes application into account (by looking up a utility in it that knows what scope the application has)

* convince the session factory to look up application specific configuration information the first time a new scope is entered.

This means that if we have a central register of ScopedSessions, then we must key it by some unique application id (path I guess).

def application_session(app):
    return registry[app.getPath()]()
  except KeyError:
return registry.setdefault(app.getPath(), scoped_session(sessionmaker(**app.getConfiguration())))()

I don't understand, why is a further registry necessary? What is wrong with the modified scopefunc I suggested (using path or whatever you prefer to key it)? Then you don't need a registry of ScopedSessions, ScopedSession *is* that registry...

  def our_scope_func():
     return (component.getUtility(ISessionSiteScope).applicationScope(),

where applicationScope could be the path or the unique id or whatever would be best for the application, as long as it's unique per app.

Then we also introduce a custom session factory that does a utility lookup for its configuration (I'm handwaving hopefully non-essential details here):

  def our_session_factory():
      config = component.getUtility(ISessionSiteScope).configuration()
      return sessionmaker(**config)()

  Session = scoped_session(our_session_factory, our_scope_func)

ScopedSession should then take care of the rest. ISessionSiteScope is looked up each time you instantiate Session. 'configuration()' is only called the *first* time you instantiate a session in a particular scope, after that the configuration is cached.

My point about using adapters, or indeed properties to access the session, is that the only object needing to access the session which cannot look it up directly with Session.object_session(object) is the application root object. To me it seems simpler to do this than to register utilities. Also it would be nice to have a consistent way to lookup the session.

I think we can agree that the ideal way to look up the session would be to allow the following in applications, right?

  from zope.rdbintegration import Session

  session = Session()

and then session would always be an appropriately configured session for the current scope. Now please explain to me why what I sketched out above can't work. :)

(note that if you want two cooperating applications each using their own session, you're required to use setSite() before you call into the second application. This is required anyway to make other local utility lookups work properly for that other application, so this is not an extra burden on developers)



Zope-Dev maillist  -  Zope-Dev@zope.org
**  No cross posts or HTML encoding!  **
(Related lists - http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )

Reply via email to