[Zope3-dev] ZopePublication performs auth outside transaction

Phillip J. Eby pje@telecommunity.com
Fri, 25 Apr 2003 15:19:35 -0400


At 02:53 PM 4/25/03 -0400, Jeremy Hylton wrote:
>On Wed, 2003-04-23 at 12:36, Phillip J. Eby wrote:
> > Another thing that suggests it's a hack (or at least that the policy has
> > outlived its usefulness): the recent suspend() and resume() don't make
> > sense except in the context of a fixed policy for threaded
> > transactions!  If you aren't required to have a singleton transaction per
> > thread, there's no need to "suspend" one; just stop working on it and use
> > another one.
> >
> > So, at the least, suspend()/resume() appears to me to be a hack to work
> > around the fixed policy.  :)
>
>The single-threaded transaction manager also supports suspend() and
>resume().  They provide a way for suspending the current transaction and
>resuming it later, regardless of how you determine what the current
>transaction is.  It doesn't have anything to do with threads.
>
>Use case: A server program executes transactions on behalf of clients in
>response to RPC requests.  A single transaction can span multiple RPCs.
>The server uses suspend()/resume() to associate the action of a new RPC
>with the proper transaction.  This is necessary in both a multi-threaded
>server and a single-threaded, event-based server.

You're missing my point.  This wouldn't be necessary if you weren't making 
an assumption that there's only one transaction per thread.  Consider your 
use case.  If I just created a transaction manager per client, why would I 
need to "suspend" or "resume" the transactions?  I could just leave them 
sitting there.  This is in fact the natural and obvious way to do it, if 
you don't assume that there has to be "the" transaction.


>[Suggestion for expending the thread API]
> > * Expose an API to create a transaction manager (in current ZODB4 
> parlance)
> > directly.
>
>How about adding set_manager() to transaction.__init__?
>
>This creates a module global with mutable state.  I don't like that too
>much, but I really like the simplicity of get_transaction().  I'm can't
>tell how much of a problem it would be if an application could only have
>one transaction manager.  Hmm... I guess get_transaction() calls on the
>default transaction manager, but there's no reason an application
>couldn't interact with a manager explicitly if it wanted to.

Right.  Then suspend/resume is meaningless.



> > * Rename 'get_transaction()' to 'getDefaultTransactionForThread()' or some
> > such.  (Explicit is better than implicit.)
>
>Yuck.  get_transaction() calls a method on the current transaction
>manager, it's not specific to threads.

There shouldn't BE a "current transaction manager".  That's my point.  If 
there is no such thing as a "current" TM, then there is no need to suspend 
transactions, only to have multiple TM's.

For simple things, it makes sense to have a useful way to get and use a 
"default" transaction or manager.  But you should not be required to always 
get and use it; for many scenarios, explicit ownership and use of a 
dedicated TM is a much more natural paradigm.  And contextual acquisition 
of a TM is the most straightforward way to "distribute" the service.  So, 
IMO, having a placeful TransactionService is the way to go.  If you use 
components that need a transaction service, you can put them in a place 
that either has its own TM, or one that shares the "global" TM.  The 
components don't need to care.

For apps not using the Zope 3 Component Architecture, they can still call 
'getDefaultTM()' or whatever name you want to call it.  I'd prefer *not* 
get_transaction(), unless Zope 3 developers calling get_transaction() will 
actually get their "local" TM service when they call it.  Otherwise, code 
using 'get_transaction()' in Zope 3 will break when local transactions are 
used.  I'd prefer it to be named something else that makes it clear that 
what they're asking for is not what they should be asking for.

One alternative is to do away with 'get_transaction()' altogether, and 
simply require ZODB4 apps to create a transaction manager, and explicitly 
supply it to the ZODB objects that need it.  That's not really going to add 
much code footprint for the simple cases, but it *will* make it abundantly 
clear how to do anything "advanced" with transactions.