[ZODB-Dev] transaction: synchronizer newTransaction() behavior

Jim Fulton jim at zope.com
Sat Mar 9 13:50:09 UTC 2013


On Fri, Mar 8, 2013 at 9:54 PM, Siddhartha Kasivajhula
<CountVajhula at gmail.com> wrote:
> Hi there,
> I've been discussing this issue with Laurence Rowe on the pylons-dev mailing
> list, and he suggested bringing it up here.
>
> I'm writing a MongoDB data manager for the python transaction package:
> https://github.com/countvajhula/mongomorphism
> I noticed that for a synchronizer, the beforeCompletion() and
> afterCompletion() methods are always called once the synch has been
> registered, but the newTransaction() method is only called when an explicit
> call to transaction.begin() is made. Since it's possible for transactions to
> be started without this explicit call, I was wondering if there was a good
> reason why these two cases (explicitly vs implicitly begun transactions)
> would be treated differently.

Nope. This is a bug.

> That is, should the following two cases not be
> equivalent, and therefore should the newTransaction() method be called in
> both cases:
>
> (1)
> t = transaction.get()
> t.join(my_dm)
> ..some changes to the data..
> transaction.commit()
>
> and:
>
> (2)
> transaction.begin()
> t = transaction.get()
> t.join(my_dm)
> ..some changes to the data..
> transaction.commit()

Only if (1) was was preceded by an ``abort``. The definition of
``get`` is to get the current transaction, creating one, if necessary.

Really, ``begin` and ``abort`` are equivalent.  It might be better if
there wasn't a ``begin`` method, as it's missleading. One should be an
alias for the other. I'd be for deprecating ``begin``. The call to
``_new_transaction`` should be moved to the point in ``get`` where a
new transaction is created, and ``begin`` should be made an alias for
``abort``.


> In my mongo dm implementation, I am using the synchronizer to do some
> initialization before each transaction gets underway, and am currently
> requiring explicit calls to transaction.begin() at the start of each
> transaction. Unfortunately, it appears that other third party libraries
> using the transaction library may not be calling begin() explicitly, and in
> particular my data manager doesn't work when used with pyramid_tm.
>
> Another thing I noticed was that a synchronizer cannot be registered like
> so:
> transaction.manager.registerSynch(MySynch())
> .. and can only be registered like this:
> synch = MySynch()
> transaction.manager.registerSynch(synch)
>
> ... which I'm told is due to MySynch() being stored in a "WeakSet" which
> means it gets garbage collected. Currently this means that I'm retaining a
> reference to the synch as a global that I never use. Just seems a bit
> contrived so thought I'd mention that as well, in case there's anything that
> can be done about that.

This is to prevent memory leaks.  Normally, the synchronizier is
associated with a database. For example, the synchronizers are
database connection methods.  A stand-alone synchronizer seems weird
to me.

Jim

--
Jim Fulton
http://www.linkedin.com/in/jimfulton
Jerky is better than bacon! http://zo.pe/Kqm


More information about the ZODB-Dev mailing list