[ZODB-Dev] preventing a transaction from committing within appcode

Tim Peters tim at zope.com
Wed Sep 8 22:01:32 EDT 2004


[Dieter Maurer]
> This has been discussed before. There was a real proposal.
> But Jeremy asked why not simply add a transaction client (via
> "transaction.register") that raises an exception on "tpc_vote".
>
> Thus, you get what you want without any API change.
>
> The proposer was convinced by Jeremys argument.

Chris, did that make sense to you?  Even Jeremy has apparently forgotten
that by now <wink>, but it should work.  Here's a concrete example that
works as the comments say it works:

"""
import ZODB
from ZODB.FileStorage import FileStorage

class ChrisError(Exception):
    pass

# Implement our own jar.  There's just enough so that
# Transaction.commit() can get an exception raised by
# this jar's tpc_vote().
class DeathByChris:
    def sort_key(self):
        return "something unlikely to match anything else"

    def tpc_begin(self, transaction):
        pass

    def commit(self, obj, transaction):
        pass

    def tpc_vote(self, transaction):
        raise ChrisError("no way")

DeathJar = DeathByChris()

# Some class that claims its instances have DeathJar
# as their jar.
class Deadly:
    def __init__(self):
        self._p_jar = DeathJar

TransactionKiller = Deadly()

# Vanilla.
st = FileStorage("Data.fs")
db = ZODB.DB(st)
cn = db.open()
rt = cn.root()
rt['a'] = 1

# Make the transaction uncommitable.
get_transaction().register(TransactionKiller)

# Let's look at the registered objects.
print "_objects:", get_transaction()._objects

# Show that the transaction cannot commit
# now.  It sees the exception raised in
# DeathByChris.tpc_vote().
try:
    get_transaction().commit()
except Exception, detail:
    print "raised exception:", detail

# But it's still the case that we're magically
# in a new transaction:  _objects is an empty list.
print "_objects:", get_transaction()._objects

# And despite appearance, this doesn't really do
# anything.
get_transaction().commit()

# And this should raise KeyError -- we lost
# the change to rt.
print rt['a']
"""




More information about the ZODB-Dev mailing list