[ZODB-Dev] Re: [Zope-dev] Re: post publishing hook

Tim Peters tim at zope.com
Mon Apr 4 14:31:22 EDT 2005


[Jim Fulton]
...
>  From reading the source. they don't seem to fit the use case very well:
>
> - They are registered with the TM and are called for subsequent
>    transactions until they are unregistered.  This is not what we want
>    here.  We want hooks to be called only if the current transaction
>    commits.  We want to throw the hooks away at the end of the
>    transaction.
>    It's not obvious how to make this work with synchronizers.  (I suppose
>    the syncronizer could save the transaction it cares about
>    and unregister itself if it sees another.  This is a lot of bother.)

It's curious to consider the ways in which this fails to work:

"""
import transaction

class OneShot:
    def __init__(self, hook, *args, **kws):
        self.hook = hook
        self.args = args
        self.kws = kws
        self.txnmgr = transaction.manager
        self.txnmgr.registerSynch(self)

    def beforeCompletion(self, txn):
        self.hook(*self.args, **self.kws)

    def afterCompletion(self, txn):
        self._remove()

    def _remove(self):
        try:
            self.txnmgr.unregisterSynch(self)
        except KeyError:
            pass
"""

That is, OneShot(hook, ...) tries to work exactly the same way as your
beforeCommitHook(hook, ...).

The most obvious failure is that the hook gets called on both commit() and
abort().  I view that as a mistake in the design of beforeCompletion; there
are currently no uses of beforeCompletion() anywhere in ZODB, so I doubt it
would cause any pain to change that.  Perhaps the hook method could be
passed a string arg, 'commit' or 'abort'.

A subtler failure is that "are called for subsequent transactions until they
are unregistered" isn't the full truth:  the TM holds only a weak reference
to a registered synchronizer.  If such a synchronizer becomes otherwise
unreferenced, it will vanish from the TM's weak set of registered
synchronizers, and then its methods won't get invoked at all.  If the caller
arranges to hold a strong reference to a OneShot instance until the current
transaction ends, then that part isn't an issue.




More information about the ZODB-Dev mailing list