Skip to content

keyspace: unassign tombstone keyspace from meta service group#10959

Open
bufferflies wants to merge 4 commits into
tikv:masterfrom
bufferflies:pr-cp-10891-unassign-tombstone-ms-group
Open

keyspace: unassign tombstone keyspace from meta service group#10959
bufferflies wants to merge 4 commits into
tikv:masterfrom
bufferflies:pr-cp-10891-unassign-tombstone-ms-group

Conversation

@bufferflies

@bufferflies bufferflies commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: Close #10891

This is a cherry-pick of 60279ef from the PD microservices branch.

Original author: @ystaticy

Problem Summary:

When a keyspace is moved to TOMBSTONE, it could still keep meta_service_group_id in its config and the meta service group assignment counter could remain inflated. That stale assignment can block deleting an otherwise-empty meta service group.

What is changed and how does it work?

  • Unassign a keyspace from its meta service group in the same transaction when the keyspace transitions to TOMBSTONE.
  • Remove meta_service_group_id from the keyspace config and decrement the persisted assignment count through the meta service group manager.
  • Reuse the same unassignment helper from RemoveKeyspace so removal and tombstone paths keep assignment accounting consistent.
  • Adapt the cherry-pick to current master, which keeps the existing UpdateKeyspaceState API.
  • Add regression coverage for tombstoning an assigned keyspace and verifying both metadata cleanup and assignment count decrement.

Check List

Tests

  • Unit test

Code changes

  • Has persistent data change

Side effects

  • No compatibility impact

Related changes

  • Need to cherry-pick to the release branch

Release note

Unassign keyspace from meta service group when setting it to tombstone.

Validation

  • GOFLAGS=-buildvcs=false make gotest GOTEST_ARGS='./pkg/keyspace -run TestKeyspaceTestSuite/TestTombstoneKeyspaceUnassignsMetaServiceGroup -count=1 -timeout=5m'
  • GOFLAGS=-buildvcs=false make gotest GOTEST_ARGS='./pkg/keyspace -run TestKeyspaceTestSuite/TestUpdateKeyspaceState -count=1 -timeout=5m'
  • git diff --check && git diff --cached --check
  • GOFLAGS=-buildvcs=false make check

Summary by CodeRabbit

  • Bug Fixes
    • Keyspaces transitioned to TOMBSTONE now unbind their MetaServiceGroup configuration and clear the persisted assignment, preventing stale counter effects.
    • MetaServiceGroup assignment updates are now applied transaction-scope with keyspace meta updates to keep metrics consistent across state changes.
    • RemoveKeyspace no longer over-decrements the MetaServiceGroup assignment counter for already-tombstoned keyspaces.
  • Tests
    • Added coverage for DISABLED/ARCHIVED → TOMBSTONE, idempotent TOMBSTONE re-application “repair,” and counter correctness after removal.

…tikv#399)

(cherry picked from commit 60279ef)
Signed-off-by: bufferflies <1045931706@qq.com>
@ti-chi-bot ti-chi-bot Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. do-not-merge/needs-triage-completed dco-signoff: yes Indicates the PR's author has signed the dco. labels Jul 1, 2026
@bufferflies

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@ti-chi-bot ti-chi-bot Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 51c7f733-84f8-4698-9f33-d64a15f979f1

📥 Commits

Reviewing files that changed from the base of the PR and between ee51cbe and 6aa5851.

📒 Files selected for processing (1)
  • pkg/keyspace/keyspace.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/keyspace/keyspace.go

📝 Walkthrough

Walkthrough

Keyspace state transitions now use the active transaction when updating state, and TOMBSTONE clears the meta-service group assignment within the same transaction. Removal also reuses the same unassignment helper. A new test covers config cleanup and assignment-count reset.

Changes

Keyspace tombstone unassignment

Layer / File(s) Summary
Transactional unassignment helper and TOMBSTONE handling
pkg/keyspace/keyspace.go
Adds unassignKeyspaceFromMetaServiceGroup(txn, meta), changes transformKeyspaceState to accept txn, and unassigns meta-service group bindings during TOMBSTONE transitions before updating state and timestamps.
Wiring callers to pass transaction and use helper
pkg/keyspace/keyspace.go
UpdateKeyspaceState, UpdateKeyspaceStateByID, and RemoveKeyspace now route through the transactional unassignment path instead of inline meta-service-group decrement logic.
Test coverage for tombstone unassignment
pkg/keyspace/keyspace_test.go
Adds TestTombstoneKeyspaceUnassignsMetaServiceGroup, verifying MetaServiceGroupIDKey removal and assignment-count reset after transitioning a keyspace to TOMBSTONE.

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

Possibly related PRs

  • tikv/pd#10904: Also changes meta-service-group assignment counter handling in code paths used by keyspace tombstone/unassign logic.

Suggested reviewers: rleungx, lhy1024

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: unassigning tombstoned keyspaces from meta service groups.
Description check ✅ Passed The description covers the issue, change summary, tests, release note, and validation, so it matches the template well.
Linked Issues check ✅ Passed The PR satisfies #10891 by clearing meta_service_group_id and decrementing the assignment count when a keyspace becomes TOMBSTONE.
Out of Scope Changes check ✅ Passed The changes stay focused on tombstone unassignment logic and its regression test, with no evident unrelated scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/keyspace/keyspace.go (1)

1124-1136: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Run TOMBSTONE cleanup before the same-state early return.

Line 1125 returns before the new TOMBSTONE unassignment branch, so an already-TOMBSTONE keyspace that still has MetaServiceGroupIDKey cannot be repaired by reapplying the TOMBSTONE update; its assignment count can remain inflated.

Proposed fix
 	// If already in the target state, do nothing and return.
 	if meta.GetState() == newState {
+		if newState == keyspacepb.KeyspaceState_TOMBSTONE {
+			return manager.unassignKeyspaceFromMetaServiceGroup(txn, meta)
+		}
 		return nil
 	}
🤖 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/keyspace/keyspace.go` around lines 1124 - 1136, In the state transition
logic in keyspace state update handling, the TOMBSTONE cleanup branch is being
skipped when the current state already matches the requested state. Move the
TOMBSTONE unassignment path in the keyspace state change flow so it runs before
the early same-state return, and make sure the transition logic around
meta.GetState(), newState, and manager.unassignKeyspaceFromMetaServiceGroup
still preserves the existing legal-transition checks.
🤖 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.

Outside diff comments:
In `@pkg/keyspace/keyspace.go`:
- Around line 1124-1136: In the state transition logic in keyspace state update
handling, the TOMBSTONE cleanup branch is being skipped when the current state
already matches the requested state. Move the TOMBSTONE unassignment path in the
keyspace state change flow so it runs before the early same-state return, and
make sure the transition logic around meta.GetState(), newState, and
manager.unassignKeyspaceFromMetaServiceGroup still preserves the existing
legal-transition checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4f63bc81-1b3d-4afb-b984-5d1078510333

📥 Commits

Reviewing files that changed from the base of the PR and between 5c811b2 and 4033bce.

📒 Files selected for processing (2)
  • pkg/keyspace/keyspace.go
  • pkg/keyspace/keyspace_test.go

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/keyspace/keyspace.go (1)

1124-1136: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Run TOMBSTONE cleanup before returning on same-state updates.

Line 1125 returns before the new TOMBSTONE cleanup, so a legacy keyspace already in TOMBSTONE but still carrying meta_service_group_id stays assigned and can continue blocking group deletion.

Proposed fix
 	// If already in the target state, do nothing and return.
 	if meta.GetState() == newState {
+		if newState == keyspacepb.KeyspaceState_TOMBSTONE {
+			return manager.unassignKeyspaceFromMetaServiceGroup(txn, meta)
+		}
 		return nil
 	}
🤖 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/keyspace/keyspace.go` around lines 1124 - 1136, The state update logic in
the keyspace transition path returns early when meta.GetState() already matches
newState, which skips the new TOMBSTONE cleanup. Update the same-state branch in
the state transition handling so that when the target state is
keyspacepb.KeyspaceState_TOMBSTONE, manager.unassignKeyspaceFromMetaServiceGroup
is still invoked before returning. Keep the legality checks and tombstone
cleanup consistent in the keyspace state update flow so legacy tombstoned
keyspaces are always unassigned.
🤖 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.

Outside diff comments:
In `@pkg/keyspace/keyspace.go`:
- Around line 1124-1136: The state update logic in the keyspace transition path
returns early when meta.GetState() already matches newState, which skips the new
TOMBSTONE cleanup. Update the same-state branch in the state transition handling
so that when the target state is keyspacepb.KeyspaceState_TOMBSTONE,
manager.unassignKeyspaceFromMetaServiceGroup is still invoked before returning.
Keep the legality checks and tombstone cleanup consistent in the keyspace state
update flow so legacy tombstoned keyspaces are always unassigned.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f520cbd-6c91-458f-b38b-772e4d8e57bf

📥 Commits

Reviewing files that changed from the base of the PR and between 5c811b2 and 4033bce.

📒 Files selected for processing (2)
  • pkg/keyspace/keyspace.go
  • pkg/keyspace/keyspace_test.go

Address review follow-ups on the tombstone unassignment change:
- Tighten the RemoveKeyspace comment now that the accounting logic lives
  in the shared helper.
- Add GoDoc to unassignKeyspaceFromMetaServiceGroup explaining the
  idempotent no-op after the config key is cleared and the metaLock
  requirement.
- Extend the regression test to remove the tombstoned keyspace and assert
  the assignment counter is not decremented a second time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: tongjian <1045931706@qq.com>
@ti-chi-bot ti-chi-bot Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jul 3, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: ystaticy
Once this PR has been reviewed and has the lgtm label, please assign overvenus for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found 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 6, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

[LGTM Timeline notifier]

Timeline:

  • 2026-07-06 03:35:26.169972944 +0000 UTC m=+615267.870352347: ☑️ agreed by ystaticy.

@ystaticy

ystaticy commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

/retest

Comment thread pkg/keyspace/keyspace_test.go Outdated
groupID := "etcd-group-0"
metaServiceGroupStore, ok := manager.store.(endpoint.MetaServiceGroupStorage)
re.True(ok)
manager.mgm = NewMetaServiceGroupManager(metaServiceGroupStore, map[string]string{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This group is disabled by default, so CreateKeyspace leaves meta_service_group_id empty and the test fails in CI.

Comment thread pkg/keyspace/keyspace.go
if !slice.Contains(stateTransitionTable[meta.GetState()], newState) {
return errors.Errorf("cannot change keyspace state from %s to %s", meta.GetState().String(), newState.String())
}
if newState == keyspacepb.KeyspaceState_TOMBSTONE {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This branch is skipped when the keyspace is already TOMBSTONE, so legacy tombstoned keyspaces with meta_service_group_id remain assigned.

Address review feedback from @rleungx:
- transformKeyspaceState returned early on a same-state update, so a
  keyspace already in TOMBSTONE that still carried meta_service_group_id
  (e.g. tombstoned before this cleanup existed) could never be unassigned
  and kept an inflated group assignment count. Run the idempotent
  unassignment on same-state TOMBSTONE updates too.
- Make TestTombstoneKeyspaceUnassignsMetaServiceGroup independent of
  meta-service-group auto-assignment at creation time (disabled by
  default): create without a group, then assign explicitly. Add coverage
  for the legacy re-tombstone repair path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: tongjian <1045931706@qq.com>
Comment thread pkg/keyspace/keyspace.go Outdated
if manager.mgm == nil {
return nil
}
manager.mgm.RLock()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This can deadlock with the existing config update path. UpdateKeyspaceState and RemoveKeyspace hold the keyspace metaLock before reaching this RLock, while updateKeyspaceConfigTxn runs under runTxnWithMetaGroupLock, so it holds mgm.RLock before taking the same metaLock. Once UpdateGroupsSafely is waiting on mgm.Lock, Go RWMutex blocks new readers, leaving the tombstone/remove path waiting here and the config-update path waiting on metaLock.

Reported by @rleungx: unassignKeyspaceFromMetaServiceGroup ran under the
keyspace metaLock and then took mgm.RLock, while the config-update path
(updateKeyspaceConfigTxn via runTxnWithMetaGroupLock) takes mgm.RLock
before metaLock. Once UpdateGroupsSafely waits on mgm.Lock, Go RWMutex
blocks new readers, so the tombstone/remove path and the config-update
path deadlock on the inverted lock order.

Drop the read lock: updateAssignmentTxn only touches the store, the
original RemoveKeyspace path never held it, and the group delete guard
relies on the authoritative keyspace scan rather than this counter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: tongjian <1045931706@qq.com>
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.42105% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.23%. Comparing base (5c811b2) to head (6aa5851).
⚠️ Report is 13 commits behind head on master.

❌ Your patch check has failed because the patch coverage (68.42%) is below the target coverage (74.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #10959      +/-   ##
==========================================
+ Coverage   79.20%   79.23%   +0.02%     
==========================================
  Files         541      541              
  Lines       75450    75692     +242     
==========================================
+ Hits        59762    59973     +211     
- Misses      11456    11481      +25     
- Partials     4232     4238       +6     
Flag Coverage Δ
unittests 79.23% <68.42%> (+0.02%) ⬆️

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.

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

Labels

dco-signoff: yes Indicates the PR's author has signed the dco. do-not-merge/needs-triage-completed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. release-note Denotes a PR that will be considered when it comes time to generate release notes. 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.

60279efd unassign keyspace from meta service group when setting tombstone

3 participants