Skip to content

tso: update keyspace group revision after initial load#10981

Open
rleungx wants to merge 13 commits into
tikv:masterfrom
rleungx:fix-testserver-run-deadlock
Open

tso: update keyspace group revision after initial load#10981
rleungx wants to merge 13 commits into
tikv:masterfrom
rleungx:fix-testserver-run-deadlock

Conversation

@rleungx

@rleungx rleungx commented Jul 6, 2026

Copy link
Copy Markdown
Member

What problem does this PR solve?

Issue Number: Close #10551

TestUpdateMemberWhenRecovery can still fail after a TSO node restart. The restarted TSO server loads keyspace group metadata from etcd, but its local keyspace group mod revision can remain 0 after the initial load. When an existing client asks with a newer service-discovery mod revision, the server rejects the request as stale even though it already has the keyspace group metadata.

What is changed and how does it work?

tso: update keyspace group revision after initial load

After `LoopWatcher` finishes its initial etcd load, expose the loaded snapshot revision and use it to refresh `KeyspaceGroupManager`'s local mod revision. This keeps restarted TSO servers from rejecting clients with a valid newer revision while the manager already has the loaded keyspace group metadata.

The recovery test also waits for the restarted TSO node to load and serve the target keyspace group, instead of only waiting for default primary serving.

Check List

Tests

  • Unit test
  • Integration test

Test scripts

go test ./pkg/tso -run TestKeyspaceGroupManagerTestSuite/TestLoadKeyspaceGroupsSetsModRevision -count=1
cd tests/integrations && make gotest GOTEST_ARGS='./mcs/keyspace -run TestKeyspaceGroupTestSuite/TestUpdateMemberWhenRecovery -count=1 -timeout=5m'

Release note

None.

Summary by CodeRabbit

  • New Features
    • Added verification that restarted TSO nodes are keyspace-group-ready before continuing recovery checks.
  • Bug Fixes
    • Improved keyspace-group initialization to correctly record the highest observed revision during the initial load, improving consistency when no events occur.
    • Fixed keyspace-group mod-revision handling so loaded state reflects etcd’s revision constraints.
    • Improved server startup resilience by restoring the previous state if startup fails.
  • Tests
    • Added coverage to ensure keyspace-group loading sets mod revision appropriately.

@ti-chi-bot ti-chi-bot Bot added release-note-none Denotes a PR that doesn't merit a release note. dco-signoff: yes Indicates the PR's author has signed the dco. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 6, 2026
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Keyspace group loading now preserves the highest observed ModRevision, startup failures in TestServer.Run restore prior state, and the TSO recovery integration test waits for keyspace-group readiness after restart.

Changes

Mod revision tracking and recovery readiness

Layer / File(s) Summary
Keyspace group manager mod revision sync
pkg/tso/keyspace_group_manager.go, pkg/tso/keyspace_group_manager_test.go
Adds maxLoadedModRevision tracking via a new preEventsFn/putFn hook during initial etcd load, and postEventsFn advances the manager's modRevision via SetModRevision when no events occurred but a revision was loaded; a new test verifies the loaded group's revision against the stored etcd ModRevision.
TestServer startup state rollback
tests/cluster.go
Run() unlocks before startup, sets state to Running before calling server.Run(), rolls back to the previous state if startup fails, and uses a buffered channel in RunServer().
TSO recovery readiness wait
tests/integrations/mcs/keyspace/tso_keyspace_group_test.go
Adds waitTSOKeyspaceGroupReady, extends tsoTestSetup with keyspaceGroupID, and waits for keyspace-group readiness after TSO node restart in TestUpdateMemberWhenRecovery.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Etcd
  participant LoopWatcher
  participant KeyspaceGroupManager

  LoopWatcher->>Etcd: initial load (putFn per kv)
  Etcd-->>LoopWatcher: kv.ModRevision
  LoopWatcher->>LoopWatcher: track maxLoadedModRevision
  LoopWatcher->>KeyspaceGroupManager: postEventsFn (no events, maxLoadedModRevision>0)
  KeyspaceGroupManager->>KeyspaceGroupManager: SetModRevision(maxLoadedModRevision)
Loading
sequenceDiagram
  participant TestSuite
  participant TSONode
  participant Etcd
  participant KeyspaceGroupManager

  TestSuite->>TSONode: restart node
  TestSuite->>Etcd: poll keyspace-group KV
  Etcd-->>TestSuite: KV with ModRevision
  TestSuite->>KeyspaceGroupManager: check loaded group ID and revision
  KeyspaceGroupManager-->>TestSuite: group ID, loaded revision
  TestSuite->>TestSuite: confirm keyspace serving by group
  TestSuite->>TSONode: proceed with recovery assertions
Loading

Possibly related PRs

  • tikv/pd#10285: Both PRs adjust TestUpdateMemberWhenRecovery to wait for keyspace-group readiness after TSO restart before asserting recovery behavior.
  • tikv/pd#10442: Both PRs change recovery-test waiting logic around restarted TSO readiness and keyspace-group state.
  • tikv/pd#10943: Both PRs adjust keyspace-group manager modRevision handling used by TSO readiness checks.

Suggested labels: lgtm, approved

Suggested reviewers: bufferflies, lhy1024, JmPotato

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: updating TSO keyspace group revision after initial load.
Description check ✅ Passed The PR description matches the template with issue number, problem, change summary, tests, and release note.
Linked Issues check ✅ Passed The changes address the recovery race by waiting for keyspace group readiness before the timestamp assertion.
Out of Scope Changes check ✅ Passed The modified files stay within the TSO recovery and test-stabilization scope, with no clearly unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/utils/etcdutil/etcdutil_test.go (1)

470-496: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider a tighter assertion for GetLoadedRevision.

re.GreaterOrEqual(watcher.GetLoadedRevision(), targetRevision) only proves the loaded revision is not stale; it would not catch a bug where the -1 offset is dropped or doubled, since either mistake still yields a value >= targetRevision. Since this test guards the exact race-condition fix targeted by this PR, a precise equality check (e.g., putting the key, then comparing against the exact revision returned by a subsequent Get/resp.Header.Revision) would give stronger regression protection.

🤖 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 `@pkg/utils/etcdutil/etcdutil_test.go` around lines 470 - 496, The
TestGetLoadedRevision assertion is too loose and won’t catch an incorrect
revision offset calculation. Update the test in loopWatcherTestSuite to verify
the exact loaded revision from NewLoopWatcher/GetLoadedRevision by comparing
against the expected revision from the etcd operations used in the setup, rather
than only using GreaterOrEqual. Keep the check focused on the loaded revision
behavior so it fails if the -1 offset logic is wrong.
🤖 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.

Inline comments:
In `@pkg/utils/etcdutil/etcdutil.go`:
- Around line 497-499: The batched load in the etcd watcher setup is mixing
revisions because each paginated Get in load() can observe a newer
Header.Revision, so the watcher may start from a point that skips writes between
pages. Update load() and the surrounding watcher initialization in etcdutil to
capture a single snapshot revision up front, reuse that revision for every batch
fetch, and have the final loadedRevision/watchStartRevision logic derive from
that fixed revision rather than each page’s response.

---

Nitpick comments:
In `@pkg/utils/etcdutil/etcdutil_test.go`:
- Around line 470-496: The TestGetLoadedRevision assertion is too loose and
won’t catch an incorrect revision offset calculation. Update the test in
loopWatcherTestSuite to verify the exact loaded revision from
NewLoopWatcher/GetLoadedRevision by comparing against the expected revision from
the etcd operations used in the setup, rather than only using GreaterOrEqual.
Keep the check focused on the loaded revision behavior so it fails if the -1
offset logic is wrong.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a1ed1963-6417-49a9-9731-ed548e16c7cc

📥 Commits

Reviewing files that changed from the base of the PR and between cead902 and f2a77e0.

📒 Files selected for processing (3)
  • pkg/tso/keyspace_group_manager.go
  • pkg/utils/etcdutil/etcdutil.go
  • pkg/utils/etcdutil/etcdutil_test.go

Comment thread pkg/utils/etcdutil/etcdutil.go
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.42857% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.26%. Comparing base (c2a47d8) to head (644088f).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #10981      +/-   ##
==========================================
+ Coverage   79.22%   79.26%   +0.03%     
==========================================
  Files         541      541              
  Lines       75965    76042      +77     
==========================================
+ Hits        60187    60274      +87     
- Misses      11531    11532       +1     
+ Partials     4247     4236      -11     
Flag Coverage Δ
unittests 79.26% <61.42%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ti-chi-bot

ti-chi-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bufferflies

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Jul 9, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

[LGTM Timeline notifier]

Timeline:

  • 2026-07-09 02:03:20.276522718 +0000 UTC m=+247186.312617764: ☑️ agreed by bufferflies.

@ti-chi-bot ti-chi-bot Bot added the approved label Jul 9, 2026
Comment thread pkg/tso/keyspace_group_manager.go Outdated
rleungx added 7 commits July 10, 2026 15:31
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
@rleungx rleungx force-pushed the fix-testserver-run-deadlock branch from 65b522a to 4777a56 Compare July 10, 2026 07:31
rleungx added 3 commits July 13, 2026 11:53
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
@ti-chi-bot ti-chi-bot Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 13, 2026
rleungx added 2 commits July 13, 2026 14:40
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
@ti-chi-bot ti-chi-bot Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jul 13, 2026
Signed-off-by: Ryan Leung <rleungx@gmail.com>
@rleungx

rleungx commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

/retest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved dco-signoff: yes Indicates the PR's author has signed the dco. needs-1-more-lgtm Indicates a PR needs 1 more LGTM. release-note-none Denotes a PR that doesn't merit a release note. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky: TestKeyspaceGroupTestSuite/TestUpdateMemberWhenRecovery times out with “failed to find the keyspace group”

2 participants