[ZODB-Dev] afterCommitHook
Tim Peters
tim.one at comcast.net
Thu Sep 22 15:23:51 EDT 2005
[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).
More information about the ZODB-Dev
mailing list