You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(txn): restore recovery routes and cancellation (#25956)
## What type of PR is this?
- [ ] API-change
- [x] BUG
- [ ] Improvement
- [ ] Documentation
- [ ] Feature
- [ ] Test and CI
- [ ] Code Refactoring
## Which issue(s) this PR fixes:
Fixes#25951
## What this PR does / why we need it:
Recovered prepared/committing transaction metadata may contain only
durable participant identity. Sending recovery RPCs with that metadata
currently uses an empty `ReplicaID` and address. At the same time, a
missing participant can make `TxnService.Start()` wait indefinitely,
while replica or store shutdown waits for `Start()` before it can close
the service.
This PR establishes one recovery invariant: recovery RPCs use complete
current participant routes, and TN shutdown can terminate every recovery
producer, consumer, route wait, and blocked `Start()`.
| Failure | Change |
| --- | --- |
| Recovered remote participant has no RPC route | Resolve `ShardID`
through the current TN cluster snapshot before `GetStatus` or
`CommitTNShard`; preserve a durable `LogShardID` when the snapshot omits
it. |
| Participant or cluster metadata is temporarily unavailable | Retry
lookup and authoritative refresh without sending to an incomplete route.
|
| A historical Prepared record names a retired participant but a later
Committed record supersedes it | Fold the complete recovery stream
first; resolve routes only for coordinator-owned transactions that
remain Prepared/Committing. |
| Route never appears | Add a recovery cancellation context and let
replica shutdown cancel it before waiting for `Start()`. |
| Store shutdown joins a replica task blocked in recovery | Deliver
`cancelStart` and `CancelRecovery` to replicas before stopping the store
task group; keep storage open until RPC drain completes. |
| HAKeeper never produces the initial cluster snapshot | Stop the
cluster refresh task before releasing readiness waiters, so
`Store.Close()` does not depend on metadata readiness. |
| Storage producer blocks on a read or a full recovery channel | Treat
context-canceled MEMKV reads as normal termination and make publication
select on `ctx.Done()`. |
| Multiple surviving recovery transactions share the same current TN
routes | Refresh one authoritative TN snapshot per recovery pass, reuse
it across transactions, and refresh/retry only when the shared snapshot
lacks a required route. |
Compatibility and non-goals:
- Single-participant and non-coordinator recovery keep the existing
local replay path; only coordinators with final unresolved
Prepared/Committing state refresh participant routes before sending
recovery RPCs.
- No wire or persisted format changes.
- No AUTO_INCREMENT behavior, allocator changes, maximum prepared
timestamp repair, or replay/logtail ordering changes are included.
Validation:
- `go test ./pkg/clusterservice ./pkg/txn/service ./pkg/txn/storage/mem
-count=1`
- `go test ./pkg/tnservice -count=1`
- `go test ./pkg/txn/... -count=1`
- focused recovery and store-close lifecycle tests under `-race`
- both new timing-sensitive regressions repeated 20 times
- in-flight MEMKV log-read cancellation and non-coordinator
missing-route startup
- `go vet ./pkg/clusterservice ./pkg/txn/service ./pkg/tnservice
./pkg/txn/storage/mem ./pkg/vm/engine/test/testutil`
- `go test ./pkg/... -run '^$' -count=1`
- `git diff --check`
Diff size: 8 production/interface/helper files / about 260 added
handwritten lines; 6 test files / about 850 added test lines; no
generated code.
Co-authored-by: ULookup <CHBulookup@outlook.com>
---------
Co-authored-by: ULookup <CHBulookup@outlook.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
0 commit comments