[Zope-dev] Re: zope.sqlalchemy, integration ideas

Martijn Faassen faassen at startifact.com
Fri May 30 08:32:05 EDT 2008


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):
>   try:
>     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(),
              thread.getindent())

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)

Regards,

Martijn



More information about the Zope-Dev mailing list