[BACKPORT 2026.1][#33175] DocDB: Let the already-replicated verdict win over an expired write fence (#33653) - #33664
Merged
Conversation
…n expired write fence (yugabyte#33653) ## Summary A write carrying fence F replicates, the response is dropped, and the client library resends the identical ops with the same retryable request id after F has passed. The fence check sat ahead of `RegisterRetryableRequest`, so the resend was rejected with `WRITE_FENCE_EXPIRED` ("the write did NOT take effect") instead of getting `Register`'s `AlreadyPresent` verdict -- while the row is durably present. Exactly the wrong answer for a lease holder, and every further resend repeats it. The fence is now checked after `RegisterRetryableRequest` succeeds and still before `NotifyAddedToLeader`. Rejection goes through `ReplicaState::NotifyReplicationFinishedUnlocked` so the registration is undone -- the leak that motivated the old ordering. ## Test Plan `yb_thin_client-itest` -- full suite, 12/12. New test `ReplayOfReplicatedWriteWinsOverExpiredFence` replicates a fenced write, forces the timed-out resend path, and holds it until the fence has passed: the caller must see success and exactly one row. Fails before the fix with `WRITE_FENCE_EXPIRED`. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
spolitov
approved these changes
Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes an inversion in the write fence (#33645 on this branch), found in review of that backport.
A write carrying fence F replicates, the response is dropped, and the client library resends the
identical ops with the same retryable request id after F has passed. The fence check sat ahead of
RegisterRetryableRequest, so the resend was rejected withWRITE_FENCE_EXPIRED("the write didNOT take effect") instead of getting
Register'sAlreadyPresentverdict -- while the row isdurably present. Exactly the wrong answer for a lease holder, and every further resend repeats it.
The fence is now checked after
RegisterRetryableRequestsucceeds and still beforeNotifyAddedToLeader. Rejection goes throughReplicaState::NotifyReplicationFinishedUnlockedsothe registration is undone -- the leak that motivated the old ordering.
Upgrade/Rollback safety
No wire or storage format change; reorders two admission-time checks on the tablet leader.
Original commit: 7e3517d / #33653
Test plan
yb_thin_client-itest-- full suite on 2026.1, 12/12.ReplayOfReplicatedWriteWinsOverExpiredFencereplicates a fenced write, forces the timed-outresend path, and holds it until the fence has passed: the caller must see success and exactly one
row. Fails before the fix with
WRITE_FENCE_EXPIRED.