[Tim Peters] >> ... >> OTOH, if we view the after-commit hook as running at the very start of >> "the next" transaction, the implementation becomes harder to picture >> (although the edge case semantics become clearer: the after-commit >> hooks run "in" a well-defined transaction then).
[Dieter Maurer] > But it would give very strange semantics: > > A transactions has something at its beginning, it knows nothing > about -- and this is committed or aborted depending on the > fate of this transaction. > > Bound to result in big surprises... Yes, it's unattractive. I have to say that "has something at its beginning" is too strong, the truth is more that it _may_ have something transactional at its beginning, depending entirely on what the after-commit hooks do. Non-transactional "something"s are irrelevant. Is the other way more attractive? Running after-commit hooks "at the end" of the current transaction has the same kinds of problems: Then a transaction may have something transactional at its end that's silently ignored. For example, call addBeforeCommitHook() from an after-commit hook, and the new hook will simply be thrown away uncalled. Worse, modify a persistent object from an after-commit hook, and that object's data manager will join a Transaction object (the still-current Transaction object!) that simply vanishes shortly after. The damage that follows could be spectacular: - tpc_finish marks the Connection as needing to join a Transaction, and clears the Connection's list of modified objects. - The after-commit hooks run, and one of them loads and modifies an object from the Connection. - The Connection joins the current transaction (still the same one!), and marks itself as being joined to a transaction. - The current Transaction object vanishes. - The Connection won't join the next transaction, because it believes it's already joined (before the introduction of after-commit hooks, joining a transaction was always followed by a commit or abort of that transaction, but not anymore). - As a result, no modifications to _any_ objects loaded from that Connection during the next transaction (including the object modified by the after-commit hook) will persist when the next transaction commits. I'd say that's surprising too ;-) There's no problem either way if users swear not to do "anything transactional" in after-commit hooks. It's unattractive to leave that to good intentions and/or luck, and I don't see an easy way for either approach to _prevent_ "something transactional" from happening while an after-commit hook is running. In fact I suspect we already have similar possible problems stemming from afterCompletion() ISynchronizer methods, but so far nobody (other than ZODB's own Connection) appears to be using those. I suppose a Transaction could abort() itself "just in case" after after-commit hooks ran. Then transactional changes made by after-commit hooks would be (silently) lost -- but wouldn't screw up the next transaction (which would again start with a clean slate). _______________________________________________ For more information about ZODB, see the ZODB Wiki: http://www.zope.org/Wikis/ZODB/ ZODB-Dev mailing list - ZODB-Dev@zope.org http://mail.zope.org/mailman/listinfo/zodb-dev