request: treat an undetermined apply outcome as terminal at commit points - #555
request: treat an undetermined apply outcome as terminal at commit points#555eduralph wants to merge 1 commit into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThe change adds configurable terminal handling for undetermined multi-region results. CAS and selected transaction commit paths stop retrying these results. Retry aggregation preserves undetermined errors, and transaction code converts qualifying failures to ChangesUndetermined retry semantics
Estimated code review effort: 4 (Complex) | ~45 minutes Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant Committer
participant RetryableMultiRegion
participant Region
Committer->>RetryableMultiRegion: prewrite or commit_primary with terminal retry
RetryableMultiRegion->>Region: execute request
Region-->>RetryableMultiRegion: undetermined_result region error
RetryableMultiRegion-->>Committer: return without replay
Committer-->>Committer: convert failure to Error::UndeterminedError
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
eddb093 to
4f0c54c
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
proto/encryptionpb.proto (1)
12-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueBuf compile errors here are an include-path artifact, not a file defect.
gogoproto/gogo.protoandrustproto.protolive underproto/include/; Buf resolves imports relative to its module root, so every vendored file reports the same unresolvable-option/import errors. Consider adding abuf.yaml/buf.work.yamlthat registersprotoandproto/includeas roots (or excluding vendored protos from Buf) so CI signal isn't drowned in false positives.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@proto/encryptionpb.proto` around lines 12 - 18, Update the Buf configuration rather than proto/encryptionpb.proto: register both proto and proto/include as module roots so imports of gogoproto/gogo.proto and rustproto.proto resolve, or exclude the vendored protos from Buf validation. Ensure CI no longer reports false-positive compile errors for these vendored files.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@proto/encryptionpb.proto`:
- Around line 12-18: Update the Buf configuration rather than
proto/encryptionpb.proto: register both proto and proto/include as module roots
so imports of gogoproto/gogo.proto and rustproto.proto resolve, or exclude the
vendored protos from Buf validation. Ensure CI no longer reports false-positive
compile errors for these vendored files.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ff4ddb26-826e-403b-b41f-609a275ef6b7
⛔ Files ignored due to path filters (21)
src/generated/backup.rsis excluded by!**/generated/**src/generated/cdcpb.rsis excluded by!**/generated/**src/generated/coprocessor.rsis excluded by!**/generated/**src/generated/deadlock.rsis excluded by!**/generated/**src/generated/encryptionpb.rsis excluded by!**/generated/**src/generated/errorpb.rsis excluded by!**/generated/**src/generated/import_sstpb.rsis excluded by!**/generated/**src/generated/keyspacepb.rsis excluded by!**/generated/**src/generated/kvrpcpb.rsis excluded by!**/generated/**src/generated/logbackup.rsis excluded by!**/generated/**src/generated/meta_storagepb.rsis excluded by!**/generated/**src/generated/metapb.rsis excluded by!**/generated/**src/generated/mpp.rsis excluded by!**/generated/**src/generated/pdpb.rsis excluded by!**/generated/**src/generated/raft_cmdpb.rsis excluded by!**/generated/**src/generated/raft_serverpb.rsis excluded by!**/generated/**src/generated/resource_manager.rsis excluded by!**/generated/**src/generated/resource_usage_agent.rsis excluded by!**/generated/**src/generated/schedulingpb.rsis excluded by!**/generated/**src/generated/tikvpb.rsis excluded by!**/generated/**src/generated/tsopb.rsis excluded by!**/generated/**
📒 Files selected for processing (42)
proto/VERSIONproto/autoid.protoproto/brpb.protoproto/cdcpb.protoproto/configpb.protoproto/coprocessor.protoproto/deadlock.protoproto/debugpb.protoproto/diagnosticspb.protoproto/disaggregated.protoproto/disk_usage.protoproto/encryptionpb.protoproto/enginepb.protoproto/errorpb.protoproto/gcpb.protoproto/import_kvpb.protoproto/import_sstpb.protoproto/include/eraftpb.protoproto/include/gogoproto/gogo.protoproto/include/rustproto.protoproto/keyspacepb.protoproto/kvrpcpb.protoproto/logbackuppb.protoproto/meta_storagepb.protoproto/metapb.protoproto/mpp.protoproto/pdpb.protoproto/raft_cmdpb.protoproto/raft_serverpb.protoproto/recoverdatapb.protoproto/replication_modepb.protoproto/resource_manager.protoproto/resource_usage_agent.protoproto/schedulingpb.protoproto/tikvpb.protoproto/tracepb.protoproto/tsopb.protosrc/pd/timestamp.rssrc/raw/client.rssrc/request/plan.rssrc/request/plan_builder.rssrc/transaction/transaction.rs
…ints
The re-vendored kvproto exposes errorpb.UndeterminedResult: the server telling
us the raft apply outcome is UNKNOWN. Today it falls through to the generic
region-error arm and is retried like any transient failure. For most requests
that is right, but not for a commit point, where "failed" must never be claimed
for a transaction that may already be durable.
Follow client-go's shape: its transport never retries UndeterminedResult
("should not retry ... processed by the caller", region_request.go) and each
ACTION decides. So the plan layer keeps RETRY as the default — replaying an
idempotent request resolves the uncertainty, and on backoff exhaustion the
error escapes UNCHANGED so callers can still classify it — while plans for
which a replay is unsafe opt in to terminal-on-first-sight via
retry_multi_region_terminal_on_undetermined:
- raw CAS: a replay would compare against its OWN effect and report
succeed = false for a write that happened.
- the primary commit: client-go returns ErrResultUndetermined here (commit.go)
rather than retrying.
- async-commit / 1PC prewrites: the prewrite IS the commit point. Stricter
than client-go, in the safe direction.
Shard aggregation is fixed alongside: collect::<Result<_>>() returns the first
error BY SHARD INDEX, so a lower-index shard's determinate error could mask a
higher-index shard's UndeterminedResult and tell the caller the request
definitely failed. An undetermined error from any shard now wins.
Commit paths classify the surfaced error as UndeterminedError. Two places are
deliberately conservative and say so in comments: a 1PC prewrite that sharding
downgraded to 2PC, and an undetermined error arriving from the commit plan's
resolve_lock layer rather than the commit dispatch. Both only over-report
uncertainty, which makes the caller verify instead of replay.
Split out of the kvproto re-vendor at pingyu's suggestion (tikv#550).
Tests: 4 new — terminal for opted-in plans under a generous backoff (proving
terminal, not retry-exhausted), preserved unchanged on retry exhaustion,
recognizer positive/negative, and the shard-masking hazard. 71 lib tests green.
Signed-off-by: Eduard R. <eduard@ralphovi.net>
06baed8 to
9aebc0e
Compare
Why: the re-vendored kvproto exposes
errorpb.UndeterminedResult— the server telling us theraft apply outcome is UNKNOWN. Today it falls through to the generic region-error arm and is retried
like any transient failure. For most requests that's right; for a commit point it isn't. "Failed"
must never be claimed for a transaction that may already be durable.
What: follow client-go's shape. Its transport never retries
UndeterminedResult("should notretry … processed by the caller",
region_request.go) and each action decides. So the plan layerkeeps retry as the default — replaying an idempotent request resolves the uncertainty, and on
backoff exhaustion the error escapes unchanged so callers can still classify it — while plans for
which a replay is unsafe opt in to terminal-on-first-sight:
succeed = falsefor awrite that happened.
ErrResultUndeterminedhere (commit.go) rather thanretrying.
the safe direction.
Shard aggregation is fixed alongside:
collect::<Result<_>>()returns the first error by shardindex, so a lower-index shard's determinate error could mask a higher-index shard's
UndeterminedResultand tell the caller the request definitely failed. An undetermined error fromany shard now wins.
Commit paths classify the surfaced error as
UndeterminedError. Two places are deliberatelyconservative and say so in comments: a 1PC prewrite that sharding downgraded to 2PC, and an
undetermined error arriving from the commit plan's
resolve_locklayer rather than the commitdispatch. Both only over-report uncertainty, which makes the caller verify instead of replay.
Verification: 4 new tests — terminal for opted-in plans under a generous backoff (proving
terminal, not merely retry-exhausted), preserved unchanged on retry exhaustion, recognizer
positive/negative, and the shard-masking hazard. 71 lib tests;
make checkgreen; txn/raw/failpointintegration suites green against a local api-v2 cluster.
Summary by CodeRabbit
Bug Fixes
New Features