Skip to content

tso: update keyspace group revision after initial load#10981

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

tso: update keyspace group revision after initial load#10981
rleungx wants to merge 6 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c04375cd-fbfd-4b59-a3a9-56ba4a08aa61

📥 Commits

Reviewing files that changed from the base of the PR and between 70cb523 and 65b522a.

📒 Files selected for processing (1)
  • tests/cluster.go

📝 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 Outdated
rleungx added 2 commits July 6, 2026 16:04
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.20%. Comparing base (5c811b2) to head (70cb523).
⚠️ Report is 13 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #10981      +/-   ##
==========================================
- Coverage   79.20%   79.20%   -0.01%     
==========================================
  Files         541      541              
  Lines       75450    75696     +246     
==========================================
+ Hits        59762    59952     +190     
- Misses      11456    11510      +54     
- Partials     4232     4234       +2     
Flag Coverage Δ
unittests 79.20% <100.00%> (-0.01%) ⬇️

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.

Signed-off-by: Ryan Leung <rleungx@gmail.com>
@ti-chi-bot

ti-chi-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@rleungx: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-unit-test-next-gen-2 65b522a link true /test pull-unit-test-next-gen-2

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

)
}
} else if maxLoadedModRevision > 0 {
kgm.SetModRevision(maxLoadedModRevision)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This can still leave a restarted TSO behind clients that observed a delete. During the initial load, deleted keyspace-group records have no KeyValue, so maxLoadedModRevision only reflects surviving groups; if the last metadata change is a group deletion, FindGroupByKeyspaceID will keep returning ErrKeyspaceGroupModRevisionStale even though the loaded snapshot is current.

@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
)
}
} else if maxLoadedModRevision > 0 {
kgm.SetModRevision(maxLoadedModRevision)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What should we do if SetModRevision returns false?

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/L Denotes a PR that changes 100-499 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