*** ./lib/python/Products/MailHost/MailHost.py.orig 2007-02-01 15:49:31.000000000 -0600 --- ./lib/python/Products/MailHost/MailHost.py 2007-02-01 15:52:15.000000000 -0600 *************** *** 157,162 **** --- 157,170 ---- security.declarePrivate('_send') def _send( self, mfrom, mto, messageText ): + T = get_transaction() + if hasattr(T,'afterCommitHook'): + T.afterCommitHook(getattr(self,'_really_send'), mfrom, mto, messageText) + else: + return self._really_send(mfrom, mto, messageText) + + security.declarePrivate('_really_send') + def _really_send( self, mfrom, mto, messageText ): """ Send the message """ smtpserver = SMTP(self.smtp_host, int(self.smtp_port) ) if self.smtp_uid: *** ./lib/python/transaction/_transaction.py.orig 2007-01-31 16:39:59.000000000 -0600 --- ./lib/python/transaction/_transaction.py 2007-02-01 10:22:53.000000000 -0600 *************** *** 115,120 **** --- 115,131 ---- passing it a callable and arguments. The callable will be called with its arguments at the start of the commit (but not for substransaction commits). + After-commit hook + --------------- + + Sometimes, applications want to take some action not related to the + ZODB, if the ZODB transaction commits okay. For example, you might + want to send an email, but not if the transaction doesn't commit. A + post-commit hook is available for such use cases, just use afterCommitHook() + passing it a callable and arguments. The callable will be called with its + arguments after the commit completes. + + Error handling -------------- *************** *** 238,247 **** # raised, incorporating this traceback. self._failure_traceback = None ! # Holds (hook, args, kws) triples added by beforeCommitHook. # TODO: in Python 2.4, change to collections.deque; lists can be # inefficient for FIFO access of this kind. self._before_commit = [] # Raise TransactionFailedError, due to commit()/join()/register() # getting called when the current transaction has already suffered --- 249,259 ---- # raised, incorporating this traceback. self._failure_traceback = None ! # Holds (hook, args, kws) triples added by before/afterCommitHook. # TODO: in Python 2.4, change to collections.deque; lists can be # inefficient for FIFO access of this kind. self._before_commit = [] + self._after_commit = [] # Raise TransactionFailedError, due to commit()/join()/register() # getting called when the current transaction has already suffered *************** *** 384,389 **** --- 396,404 ---- if self._manager: self._manager.free(self) self._synchronizers.map(lambda s: s.afterCompletion(self)) + + self._callAfterCommitHooks() + self.log.debug("commit") def _saveCommitishError(self): *************** *** 412,417 **** --- 427,445 ---- hook, args, kws = self._before_commit.pop(0) hook(*args, **kws) + def getAfterCommitHooks(self): + return iter(self._after_commit) + + def afterCommitHook(self, hook, *args, **kws): + self._after_commit.append((hook, args, kws)) + + def _callAfterCommitHooks(self): + # Call all hooks registered, allowing further registrations + # during processing. + while self._after_commit: + hook, args, kws = self._after_commit.pop(0) + hook(*args, **kws) + def _commitResources(self): # Execute the two-phase commit protocol.