Conversation
…, not which thread hands it out Fixes OpenIdentityPlatform#1036. getNextUpdate() hands a parked change to whichever replay thread calls it first once the changes before it have left the pending changes, and the thread which parked it calls it on its own way out - so the two OpenIdentityPlatform#958 tests which asserted isSameAs(replayingParent) failed whenever the parent's post-operation commit landed before the parker got there, and the child, which no replication server owns, then held the ServerState back for the rest of the class. Both tests now wait for the child to be seen parked before the parent is released - a parked change leaves by getNextUpdate() and by no other road, which is the hand-out they are about - and no longer assert which thread hands it out. The OpenIdentityPlatform#923 liveness assertion is made on the thread which met the Error. The javadoc of getNextUpdate() says what it guarantees.
|
@maximthomas could you take this one ahead of the queue? It is test-only - two assertions dropped, two waits added, one javadoc - one commit on master, What it is costingThe issue was filed on two hits (#981, #964, 2026-09-12). Since then the same assertion has taken down a leg on every day the replication PRs ran, on branches which touch nothing near it:
Ten legs in five days. Every one of them is the same shape - Two things make it worse than a flake to re-run. The reruns are what a reviewer sees first: a red What the PR doesNothing in Every day this waits is another row in that table. |
Fixes #1036.
Two tests of #958 -
aChangeHandedOutAsADependencyIsGivenBackWhenItsReplayIsUnwoundandtheChangesParkedBehindAChangeWhoseAckFailedAreReplayed- assertisSameAs(replayingParent):the child parked behind the parent must be replayed by the thread which committed the parent.
getNextUpdate()never guaranteed that. It hands a parked change to whichever replay thread callsit first once the changes before it have left
pendingChanges, and the thread which parked thechild calls it on its own way out, right after
addDependency(). The parent commits in thepost-operation plugin, inside
op.run(), so a parker delayed past the parent's write finds theparent gone and takes the child back itself. That is the 0.26 s failure on #981 and #964 - and,
because the assertion sits before the by-hand redelivery of a child no replication server owns,
the child then stays uncommitted at the head of
pendingChangesand the remaining 17 tests of theclass time out behind it.
The change
Test tree, plus one javadoc:
dependent-changes-size) before the parentis released. That is the property they are about - a parked change leaves by
getNextUpdate()and by no other road - and it closes a second hole the thread check hid: released on the spot,
the parent could commit before the child was taken off the queue at all, and the child would be
replayed from the queue with nothing to wait for, a pass which proves nothing.
why. The Replication: an Error in a replay kills a replay thread the pool never replaces #923 liveness assertion is made on the thread which met the Error, whichever one it was.
getNextUpdate()'s javadoc says what it guarantees: first caller once the changes before it aregone - as a rule the thread which cleared the dependency, but the parker itself when the clearing
landed before it got there.
Testing
getNextUpdate()300 ms late, every other caller 500 ms late - original testsReplica replay thread 1vsthread 0"to refer to the same object", the CI failure verbatim, second test cascadingUpdateOperationTestThe mutant is not part of the PR. The branch sits directly on
masterat 776339a, one commit.