[ZODB-Dev] preventing a transaction from committing within appcode
Chris McDonough
chrism at plope.com
Thu Sep 9 05:12:59 EDT 2004
On Wed, 2004-09-08 at 22:01, Tim Peters wrote:
> [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?
Yes it does. That's a fine idea, it solves my problem completely and
without any API changes.
> 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:
Wow, creating an example is above and beyond, thanks!
- C
>
> """
> 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