[Zope3-dev] ZopePublication performs auth outside transaction

Phillip J. Eby pje@telecommunity.com
Fri, 25 Apr 2003 18:34:17 -0400


At 04:02 PM 4/25/03 -0400, Jeremy Hylton wrote:
>On Fri, 2003-04-25 at 15:19, Phillip J. Eby wrote:
> > 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.
>
> > 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.
>
>To the contrary, it seems like this adds needless complexity to simple
>applications.  I don't want to add features for advanced applications
>that come at the cost of extra complexity for simple applications.
>
>Put another way, removing get_transaction() does not make clear to me
>how to do anything advanced with transactions.  I understand how to use
>suspend() and resume(), even in the context of explicit interactions
>with a transaction manager.  A TM has a get_transaction() method that
>returns the current transaction.  The TM provides coordination for
>independent entites to participate in a single transaction.

Okay, here's a hypothetical spelling of the API:

    from transaction import TransactionService

    txnSvc = TransactionService()

    myDB1 = DB(txnSvc, ...)
    myDB2 = DB(txnSvc, ...)

    txnSvc.begin()
    # do stuff with objects in myDB1 and myDB2
    txnSvc.commit()

Now, how is this more complex than calling 'get_transaction()'?  The only 
way in which it is more complex is that when I use a database (or perhaps 
just when I open a connection) I must explicitly pass my 'txnSvc'.  That is 
the *only* change in the amount of dead-chicken waving that takes 
place.  The steps are still:

1. import something from the transaction pacakge
2. call it with no arguments
3. call 'begin()' or 'commit()' or abort() on it

All we're adding is a step 2.1: "pass the result to the constructors of any 
data managers you intend to use."


>suspend() allows one participant to stop the current activity and start
>a new one, then later restart the previous activity.  That seems a
>useful feature.

Code sample #2:

    from transaction import TransactionService

    txnSvc = TransactionService()

    myDB1 = DB(txnSvc, ...)
    myDB2 = DB(txnSvc, ...)

    txnSvc.begin()
    # do stuff with objects in myDB1 and myDB2

    # whoops... need to do something else...
    t2 = TransactionService()
    otherDB = DB(t2, ...)

    t2.begin()
    # blah blah
    t2.commit()

    # continue on with what we were doing...

    # okay, done
    txnSvc.commit()


Notice that this doesn't require any "suspend" or "resume" - this happens 
naturally in the code flow.

It occurs to me that perhaps something else goes on with the suspending and 
resuming that you've implemented, that I'm not aware of.  But I *assume* 
that when you suspend or resume a ZODB transaction, you can't just keep 
using the same connection objects, because the cache state wouldn't be 
valid.  So you have to get another connection if you're doing a different 
transaction, right?  If so, then making transaction-to-database 
associations explicit is a big win in my proposed API because it makes it 
very visible that you need a connection that's associated with your 
subsequent transaction.

What I'm saying, though, is that even if you had made it so that 
connections somehow know to set aside their cache and create a new one, 
etc., then that's wasteful (from a code complexity and maintenance POV) 
compared to just letting the user explicitly manage it, as in the example 
above.

The only benefit that having a single TM adds, is the ability to avoid 
explicitly telling data managers what transaction they should belong 
to.  Given that the common use cases favor having few data managers (I 
assume most non-Zope ZODB apps use only one!), this is not much 
savings.  Explicit is better than implicit.

Given that this discussion is now mostly about the API exported from ZODB, 
perhaps we should redirect to zodb-dev?  Then perhaps also the user 
community can give us some indication of their feelings as well.  I would 
guess though that the interest expressed by many in Shane's "local 
transaction" system already indicates that there are other users whose apps 
have outgrown the "current transaction" model.