[ZODB-Dev] RE: [Zope-Annce] ZODB 3.2.4 release candidate 1released

Tim Peters tim at zope.com
Mon Sep 13 23:50:46 EDT 2004


A status update on the "make a failing commit() stick" idea.  That's
implemented on my box now (for ZODB 3.3), and all the ZODB tests pass again.
I'm too fried to finish writing new tests for it tonight, so it won't get
checked in today.

If any exception is raised by a T.commit() or T.commit(True) call:

- Pending changes are aborted, exactly as they were for a failing
  commit before.

- But T remains the current transaction object (from the POV of its
  transaction manager tm:  tm.get() continues to return T; in ZODB 3.3,
  Transaction objects are not reused across transactions, so that
  tm.get() continues to return T is significant).

- All subsequent attempts to do T.commit(), T.join(), or T.register()
  raise the new TransactionFailedError.  This gets at least some of
  what Shane wants:  if you try to modify a persistent object in
  this transaction, that object's resource manager (think "jar") will
  attempt to join() the transaction, and TransactionFailedError will
  get raised right away.

A TransactionFailedError has its own traceback (of course), and incorporates
the traceback of the original exception that caused the first failing
commit().  For example, this is from a messy test driver that arranged for a
subtransaction commit to fail via a damaged tpc_begin, but suppressed the
exception, and then tried to do a top-level commit:

Traceback (most recent call last):
  File "C:\Code\ZODB3.3\temp.py", line 44, in ?
    transaction.get().commit()
  File "C:\code\ZODB3.3\build\lib.win32-2.3\transaction\_transaction.py",
line 281, in commit
    self._prior_commit_failed() # doesn't return
  File "C:\code\ZODB3.3\build\lib.win32-2.3\transaction\_transaction.py",
line 215, in _prior_commit_failed
    raise TransactionFailedError("commit() previously failed, "
ZODB.POSException.TransactionFailedError: commit() previously failed, with
this traceback:

  File "C:\Code\ZODB3.3\temp.py", line 40, in ?
    transaction.get().commit(1)
  File "C:\code\ZODB3.3\build\lib.win32-2.3\transaction\_transaction.py",
line 296, in commit
    self._commitResources(subtransaction)
  File "C:\code\ZODB3.3\build\lib.win32-2.3\transaction\_transaction.py",
line 331, in _commitResources
    rm.tpc_begin(self, subtransaction)
  File "C:\code\ZODB3.3\build\lib.win32-2.3\transaction\_transaction.py",
line 546, in tpc_begin
    self.manager.tpc_begin(txn, sub)
  File "C:\Code\ZODB3.3\temp.py", line 18, in tpc_begin
    raise ChrisError("no begin")
ChrisError: no begin

I hope it won't always say ChrisError <wink>.  Capturing the original
traceback is an illusion, since the actual traceback at the time the
exception is caught only extends from _transaction.py downwards.  So the
traceback is synthesized, via appending the actual traceback to a formatted
dump of the stack showing how we got *into* _transaction.py too.  This is
only a few lines of code using Python's traceback module, but it's strained
all the same.



More information about the ZODB-Dev mailing list