[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