[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.