Skip to content

*: refactor dynamic tso switch#8780

Open
rleungx wants to merge 14 commits into
tikv:masterfrom
rleungx:remove-api-mode
Open

*: refactor dynamic tso switch#8780
rleungx wants to merge 14 commits into
tikv:masterfrom
rleungx:remove-api-mode

Conversation

@rleungx

@rleungx rleungx commented Nov 6, 2024

Copy link
Copy Markdown
Member

What problem does this PR solve?

Issue Number: ref #8477.

What is changed and how does it work?

This PR made the following changes:

  1. Merge api subcommand logic to pd. We keep the subcommand for compatibility but won't use it anymore.
  2. Only serverless use env to enable microservice, so I will use a config enable-multi-timelines to replace it in the next PR.
  3. Add more details for different scenes in both serverless and non-serverless environments.
  4. Whether enabling microservice is not relying on subcommand or system variables. We use enable-tso-dynamic-switch for the non-serverless env and enable-multi-timelines for the serverless env to manage it.
  5. Change the checkTSOService and IsServiceIndependent logic that needs attention when reviewing.
  6. Enable keyspace group by default, which adds group ID and user kind when creating keyspace. It's not ideal but considering the config is not used except for displaying, I made the change.
  7. Adapt the above changes for testing.

Check List

Tests

  • Unit test

Release note

None.

Summary by CodeRabbit

  • New Features

    • Improved TSO provider switching between PD and TSO services based on service readiness.
    • Added safer fallback to PD-backed TSO when forwarding fails or a service becomes unavailable.
    • Added protection against conflicting TSO primaries during timestamp updates.
    • Improved client retries when service modes change.
  • Bug Fixes

    • Prevented shutdown errors when TSO components are not fully initialized.
    • Embedded member-response errors are now reported correctly.
    • Improved TSO forwarding and failover behavior under concurrent load.

@ti-chi-bot

ti-chi-bot Bot commented Nov 6, 2024

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@ti-chi-bot ti-chi-bot Bot added release-note-none Denotes a PR that doesn't merit a release note. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. 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 Nov 6, 2024
@rleungx rleungx force-pushed the remove-api-mode branch 2 times, most recently from baece73 to e252d4c Compare November 7, 2024 03:33
@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 Nov 12, 2024
@codecov

codecov Bot commented Nov 28, 2024

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.04878% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.97%. Comparing base (31a0ad6) to head (877c5be).
⚠️ Report is 540 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8780      +/-   ##
==========================================
- Coverage   76.29%   75.97%   -0.32%     
==========================================
  Files         465      465              
  Lines       70539    70567      +28     
==========================================
- Hits        53816    53616     -200     
- Misses      13376    13618     +242     
+ Partials     3347     3333      -14     
Flag Coverage Δ
unittests 75.97% <78.04%> (∅)

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.

@rleungx rleungx marked this pull request as ready for review November 29, 2024 09:33
@ti-chi-bot ti-chi-bot Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 29, 2024

@okJiang okJiang left a comment

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.

Is there any test results?

@okJiang okJiang left a comment

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.

Please add some description about these changes.

Comment thread server/server.go Outdated

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.

Suggested change
log.Info("campaign %PD leader meets error due to txn conflict, another PD/API server may campaign successfully",
log.Info("campaign PD leader meets error due to txn conflict, another PD/API server may campaign successfully",

Comment thread server/apiv2/handlers/micro_service.go Outdated

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.

If access pd mode server, will it return 500?

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.

After this PR, there won't be pd mode anymore.

Comment thread server/cluster/cluster.go Outdated

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.

If SchedulingFallbackEnabled is false and there is no scheduling server, will we not try to start scheduling service in pd server?

@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 Jan 8, 2025
@rleungx rleungx changed the title *: remove api mode *: refactor dynamic tso Jan 10, 2025
@rleungx rleungx changed the title *: refactor dynamic tso *: refactor dynamic tso switch Jan 10, 2025
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>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 1, 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

Changes

TSO provider coordination

Layer / File(s) Summary
Storage fencing and allocator handoff
pkg/storage/..., pkg/tso/...
Timestamp persistence checks for an existing TSO primary, while allocator initialization and updates stop or reset without resigning leadership.
Client service-mode transitions
client/...
Service-mode changes use atomic snapshots, versioned preparation, mode-change notifications, and retry-aware TSO futures.
Cluster switching and forwarding
server/cluster/..., server/forward.go, server/grpc_service.go
TSO readiness discovery, embedded request gating, provider switching, forwarding retries, and PD fallback are added.
Registration and supporting updates
pkg/mcs/..., server/api/member.go, pkg/utils/apiutil/..., tools/..., tests/...
Service registration helpers, error handling, redirect behavior, test configuration, simulator wiring, and integration coverage are updated.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: JmPotato, ystaticy, okJiang, lhy1024

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.02% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and accurately summarizes the main dynamic TSO switch refactor.
Description check ✅ Passed The description matches the template structure, includes the issue line, change summary, tests, and release note placeholder.
✨ 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: 4

Caution

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

⚠️ Outside diff range comments (1)
tests/cluster.go (1)

455-510: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Range the original cluster map, not the new empty one.
newTestCluster.servers is allocated empty here, so the loop never restarts any server and the function returns a cluster with no servers and no error. Range over cluster.servers instead.

🤖 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 `@tests/cluster.go` around lines 455 - 510, The restart logic in
restartTestCluster is iterating over the newly allocated empty servers map, so
no servers are restarted. Update the loop to range over the existing
cluster.servers map, while keeping the rest of the
NewTestServer/serverMap/errorMap flow intact, so each original TestServer is
destroyed and recreated correctly.
♻️ Duplicate comments (1)
server/cluster/cluster.go (1)

404-417: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Only mark scheduling independent after discovering scheduling servers.

When fallback is disabled, Line 406 falls through to the external-service branch even if discovery failed or returned zero servers. That can stop PD scheduling jobs and mark scheduling independent with no scheduling service available.

Proposed fix
 func (c *RaftCluster) checkSchedulingService() {
 	servers, err := discovery.Discover(c.etcdClient, constant.SchedulingServiceName)
-	if c.opt.GetMicroserviceConfig().IsSchedulingFallbackEnabled() && (err != nil || len(servers) == 0) {
-		c.startSchedulingJobs(c, c.hbstreams)
-		c.UnsetServiceIndependent(constant.SchedulingServiceName)
-	} else {
-		if c.stopSchedulingJobs() || c.coordinator == nil {
-			c.initCoordinator(c.ctx, c, c.hbstreams)
-		}
-		if !c.IsServiceIndependent(constant.SchedulingServiceName) {
-			c.SetServiceIndependent(constant.SchedulingServiceName)
-		}
+	if err != nil || len(servers) == 0 {
+		if c.opt.GetMicroserviceConfig().IsSchedulingFallbackEnabled() {
+			c.startSchedulingJobs(c, c.hbstreams)
+			c.UnsetServiceIndependent(constant.SchedulingServiceName)
+			return
+		}
+		c.stopSchedulingJobs()
+		c.UnsetServiceIndependent(constant.SchedulingServiceName)
+		return
+	}
+	if c.stopSchedulingJobs() || c.coordinator == nil {
+		c.initCoordinator(c.ctx, c, c.hbstreams)
+	}
+	if !c.IsServiceIndependent(constant.SchedulingServiceName) {
+		c.SetServiceIndependent(constant.SchedulingServiceName)
 	}
 }
🤖 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 `@server/cluster/cluster.go` around lines 404 - 417, The scheduling-service
discovery logic in checkSchedulingService should not enter the external-service
path unless discovery actually found servers. Update the branching around
discovery.Discover and IsSchedulingFallbackEnabled so that failed/empty
discovery only falls back when enabled, and otherwise keeps PD scheduling jobs
running and does not call SetServiceIndependent for
constant.SchedulingServiceName. Use checkSchedulingService, startSchedulingJobs,
stopSchedulingJobs, and SetServiceIndependent/UnsetServiceIndependent to keep
the service-independent state consistent with discovery results.
🧹 Nitpick comments (1)
tests/integrations/mcs/tso/proxy_test.go (1)

65-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Stale comment: says "1 server" but creates 3.

The comment doesn't match the NewTestCluster(s.ctx, 3, ...) call.

✏️ Fix comment
-	// Create an PD cluster with 1 server
+	// Create a PD cluster with 3 servers
 	s.pdCluster, err = tests.NewTestCluster(s.ctx, 3, func(conf *config.Config, _ string) {
🤖 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 `@tests/integrations/mcs/tso/proxy_test.go` around lines 65 - 68, The inline
comment above NewTestCluster is stale and contradicts the actual cluster size
being created. Update or remove the “1 server” comment so it matches the
tests.NewTestCluster(s.ctx, 3, ...) call and the surrounding setup in
proxy_test.go, keeping the description aligned with the configured PD cluster
size.
🤖 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/apiutil/serverapi/middleware.go`:
- Around line 118-121: The redirect gate in matchMicroserviceRedirectRules
currently combines TSO and Scheduling independence with a shared check, which
can allow the /admin/reset-ts rule to be evaluated under the wrong service
condition. Split the guard in redirector.matchMicroserviceRedirectRules so TSO
redirects are checked only when constant.TSOServiceName is independent, and
scheduling redirects are checked separately for constant.SchedulingServiceName;
keep the rule matching logic aligned with the redirect registration in
server/api/server.go.

In `@server/config/config.go`:
- Line 847: The EnableMultiTimelines field in the config struct is missing
explicit TOML/JSON tags, so add matching enable-multi-timelines tags consistent
with the adjacent fields in config.go. Update the config struct definition that
includes EnableMultiTimelines to use explicit json and toml tags, following the
existing naming pattern and adding omitempty where appropriate so the field
binds and serializes correctly.

In `@server/server.go`:
- Around line 1375-1397: The non-TSO path in IsServiceIndependent can
dereference s.cluster before startServer initializes it. Update the method to
guard s.cluster (and the raft cluster state) before calling
cluster.IsServiceIndependent, and return false while the server is not fully
started or the raft cluster is nil/running state is unavailable. Keep the
existing TSO-specific logic intact, but ensure all fallback delegation to
s.cluster only happens after the cluster has been created.

In `@tests/integrations/mcs/tso/server_test.go`:
- Around line 675-678: The assertion message in the TSO service check is stale
and contradicts the current `re.NoError` expectation in `server_test.go`. Update
the failure message in the `checkTSOMonotonic` loop so it matches the intended
behavior that PD should provide TSO service, using the existing `re.NoError`
call and the surrounding TSO check logic as the anchor.

---

Outside diff comments:
In `@tests/cluster.go`:
- Around line 455-510: The restart logic in restartTestCluster is iterating over
the newly allocated empty servers map, so no servers are restarted. Update the
loop to range over the existing cluster.servers map, while keeping the rest of
the NewTestServer/serverMap/errorMap flow intact, so each original TestServer is
destroyed and recreated correctly.

---

Duplicate comments:
In `@server/cluster/cluster.go`:
- Around line 404-417: The scheduling-service discovery logic in
checkSchedulingService should not enter the external-service path unless
discovery actually found servers. Update the branching around discovery.Discover
and IsSchedulingFallbackEnabled so that failed/empty discovery only falls back
when enabled, and otherwise keeps PD scheduling jobs running and does not call
SetServiceIndependent for constant.SchedulingServiceName. Use
checkSchedulingService, startSchedulingJobs, stopSchedulingJobs, and
SetServiceIndependent/UnsetServiceIndependent to keep the service-independent
state consistent with discovery results.

---

Nitpick comments:
In `@tests/integrations/mcs/tso/proxy_test.go`:
- Around line 65-68: The inline comment above NewTestCluster is stale and
contradicts the actual cluster size being created. Update or remove the “1
server” comment so it matches the tests.NewTestCluster(s.ctx, 3, ...) call and
the surrounding setup in proxy_test.go, keeping the description aligned with the
configured PD cluster size.
🪄 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: 59ddafd6-2c6b-4205-96a0-1be31ed46977

📥 Commits

Reviewing files that changed from the base of the PR and between 50c1bbb and 5cf7aaa.

📒 Files selected for processing (55)
  • cmd/pd-server/main.go
  • pkg/keyspace/keyspace_test.go
  • pkg/mcs/discovery/register.go
  • pkg/mcs/registry/registry.go
  • pkg/storage/endpoint/tso.go
  • pkg/storage/kv/etcd_kv.go
  • pkg/storage/storage_tso_test.go
  • pkg/tso/allocator_manager.go
  • pkg/tso/global_allocator.go
  • pkg/tso/keyspace_group_manager.go
  • pkg/tso/tso.go
  • pkg/utils/apiutil/serverapi/middleware.go
  • pkg/utils/keypath/key_path.go
  • server/api/member.go
  • server/api/server_test.go
  • server/api/version_test.go
  • server/apiv2/handlers/micro_service.go
  • server/cluster/cluster.go
  • server/config/config.go
  • server/config/service_middleware_config.go
  • server/config/service_middleware_persist_options.go
  • server/server.go
  • server/server_test.go
  • server/testutil.go
  • server/util.go
  • tests/cluster.go
  • tests/integrations/client/client_test.go
  • tests/integrations/mcs/discovery/register_test.go
  • tests/integrations/mcs/keyspace/tso_keyspace_group_test.go
  • tests/integrations/mcs/members/member_test.go
  • tests/integrations/mcs/scheduling/api_test.go
  • tests/integrations/mcs/scheduling/config_test.go
  • tests/integrations/mcs/scheduling/meta_test.go
  • tests/integrations/mcs/scheduling/rule_test.go
  • tests/integrations/mcs/scheduling/server_test.go
  • tests/integrations/mcs/tso/api_test.go
  • tests/integrations/mcs/tso/keyspace_group_manager_test.go
  • tests/integrations/mcs/tso/proxy_test.go
  • tests/integrations/mcs/tso/server_test.go
  • tests/integrations/tso/client_test.go
  • tests/integrations/tso/consistency_test.go
  • tests/integrations/tso/server_test.go
  • tests/server/apiv2/handlers/keyspace_test.go
  • tests/server/apiv2/handlers/tso_keyspace_group_test.go
  • tests/server/member/member_test.go
  • tests/server/server_test.go
  • tests/server/tso/tso_test.go
  • tests/testutil.go
  • tools/pd-ctl/pdctl/command/config_command.go
  • tools/pd-ctl/tests/config/config_test.go
  • tools/pd-ctl/tests/global_test.go
  • tools/pd-ctl/tests/keyspace/keyspace_group_test.go
  • tools/pd-ctl/tests/keyspace/keyspace_test.go
  • tools/pd-simulator/main.go
  • tools/pd-simulator/simulator/client.go
💤 Files with no reviewable changes (2)
  • tools/pd-simulator/simulator/client.go
  • server/api/member.go

Comment thread pkg/utils/apiutil/serverapi/middleware.go Outdated
Comment thread server/config/config.go Outdated
// We should separate the keyspace group from the microservice later.
EnableTSODynamicSwitching bool `toml:"enable-tso-dynamic-switching" json:"enable-tso-dynamic-switching,string"`
// TODO: use it to replace system variable.
EnableMultiTimelines bool

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add the enable-multi-timelines config tags.

Line 847 leaves EnableMultiTimelines without TOML/JSON tags, so the documented micro-service.enable-multi-timelines control may not bind from config files and won’t serialize like the adjacent fields.

As per coding guidelines, “Use JSON tags explicitly; use omitempty where sensible.”

Proposed fix
-	EnableMultiTimelines bool
+	EnableMultiTimelines bool `toml:"enable-multi-timelines" json:"enable-multi-timelines,string"`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
EnableMultiTimelines bool
EnableMultiTimelines bool `toml:"enable-multi-timelines" json:"enable-multi-timelines,string"`
🤖 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 `@server/config/config.go` at line 847, The EnableMultiTimelines field in the
config struct is missing explicit TOML/JSON tags, so add matching
enable-multi-timelines tags consistent with the adjacent fields in config.go.
Update the config struct definition that includes EnableMultiTimelines to use
explicit json and toml tags, following the existing naming pattern and adding
omitempty where appropriate so the field binds and serializes correctly.

Source: Coding guidelines

Comment thread server/server.go Outdated
Comment on lines +675 to +678
// PD should provide TSO service
for range 10 {
err = checkTSOMonotonic(ctx, pdClient, &globalLastTS, 1)
re.Error(err, "TSO service should not be available")
re.NoError(err, "TSO service should not be available")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Stale assertion message contradicts inverted check.

The loop was changed to assert re.NoError (i.e., TSO should be available, per the new comment "PD should provide TSO service" on line 675), but the failure message still reads "TSO service should not be available" — a leftover from the previous logic that asserted an error. This will produce a misleading failure message if the assertion ever fails.

🐛 Proposed fix
 	// PD should provide TSO service
 	for range 10 {
 		err = checkTSOMonotonic(ctx, pdClient, &globalLastTS, 1)
-		re.NoError(err, "TSO service should not be available")
+		re.NoError(err, "TSO service should be available")
 		time.Sleep(10 * time.Millisecond)
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// PD should provide TSO service
for range 10 {
err = checkTSOMonotonic(ctx, pdClient, &globalLastTS, 1)
re.Error(err, "TSO service should not be available")
re.NoError(err, "TSO service should not be available")
// PD should provide TSO service
for range 10 {
err = checkTSOMonotonic(ctx, pdClient, &globalLastTS, 1)
re.NoError(err, "TSO service should be available")
time.Sleep(10 * time.Millisecond)
}
🤖 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 `@tests/integrations/mcs/tso/server_test.go` around lines 675 - 678, The
assertion message in the TSO service check is stale and contradicts the current
`re.NoError` expectation in `server_test.go`. Update the failure message in the
`checkTSOMonotonic` loop so it matches the intended behavior that PD should
provide TSO service, using the existing `re.NoError` call and the surrounding
TSO check logic as the anchor.

@ti-chi-bot

ti-chi-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign jmpotato 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 size/L Denotes a PR that changes 100-499 lines, ignoring generated files. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 1, 2026
Signed-off-by: Ryan Leung <rleungx@gmail.com>
@rleungx rleungx force-pushed the remove-api-mode branch from 00a3bdc to 04a6b53 Compare July 1, 2026 08:37
Signed-off-by: Ryan Leung <rleungx@gmail.com>

@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: 2

🤖 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 `@server/cluster/cluster_test.go`:
- Around line 2393-2406: The lock contention check in the test is racy because
the goroutine may not have reached c.tsoSwitchMu.Lock() before the negative
assertion runs. In cluster_test.go, update the goroutine around
switchAcquired/releaseSwitch to signal a separate “started attempting lock”
channel immediately before Lock(), then wait for that signal before asserting
the lock was not acquired. Keep the existing switchAcquired and releaseSwitch
flow, but use the new start-attempt signal to prove the provider switch is
actually contending with the embedded TSO request.

In `@server/grpc_service.go`:
- Around line 683-689: Reject zero-count TSO requests in
generateEmbeddedTSOResponse as well, so embedded mode matches the forwarding
path’s validation. Add the same Count == 0 guard before calling
s.generateEmbeddedTSO, returning the appropriate invalid-request error from
generateEmbeddedTSOResponse and keeping request handling consistent across
provider modes.
🪄 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: 3eb30988-3500-4a6d-9ac4-b9d1725149cf

📥 Commits

Reviewing files that changed from the base of the PR and between 302ad14 and b79205a.

📒 Files selected for processing (4)
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go
  • server/forward.go
  • server/grpc_service.go

Comment thread server/cluster/cluster_test.go
Comment thread server/grpc_service.go
Signed-off-by: Ryan Leung <rleungx@gmail.com>

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

🧹 Nitpick comments (1)
server/grpc_service.go (1)

623-627: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Make the retry backoff context-aware.

time.Sleep ignores stream cancellation while the forwarding slot is held. Return promptly when ctx is canceled. As per coding guidelines, “Use context-aware timeouts and backoff for retries.”

Proposed fix
 	for retry := range maxRetryTimesRequestTSOServer {
 		if retry > 0 {
-			time.Sleep(retryIntervalRequestTSOServer)
+			timer := time.NewTimer(retryIntervalRequestTSOServer)
+			select {
+			case <-ctx.Done():
+				timer.Stop()
+				return errors.WithStack(ctx.Err())
+			case <-timer.C:
+			}
 		}
 		tsoStreamErr, err = s.handleTSOForwarding(stream.Context(), forwarder, request, tsDeadlineCh)
🤖 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 `@server/grpc_service.go` around lines 623 - 627, The retry loop in
handleTSOForwarding/TSO forwarding currently uses a blocking sleep that ignores
stream cancellation, so replace the plain backoff wait with a context-aware wait
tied to stream.Context() and return immediately if the context is canceled. Keep
the retry behavior in the same loop, but ensure the pause between attempts is
interruptible by the request context or deadline so the forwarding slot is
released promptly on cancel.

Source: Coding guidelines

🤖 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 `@server/grpc_service.go`:
- Around line 623-627: The retry loop in handleTSOForwarding/TSO forwarding
currently uses a blocking sleep that ignores stream cancellation, so replace the
plain backoff wait with a context-aware wait tied to stream.Context() and return
immediately if the context is canceled. Keep the retry behavior in the same
loop, but ensure the pause between attempts is interruptible by the request
context or deadline so the forwarding slot is released promptly on cancel.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c0c4bb5-0321-4688-a088-a6987eb907fc

📥 Commits

Reviewing files that changed from the base of the PR and between b79205a and fa4e617.

📒 Files selected for processing (5)
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go
  • server/forward.go
  • server/grpc_service.go
  • server/server.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • server/forward.go
  • server/cluster/cluster_test.go

@rleungx rleungx added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jul 10, 2026

@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

🤖 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 `@server/cluster/cluster.go`:
- Around line 824-842: Move the keyspace-group discovery lookup and default TSO
readiness probe out of the tsoSwitchMu critical section in
switchTSOProviderToTSOIfServiceReady: perform all etcd reads and
isDefaultTSOServiceReady checks before acquiring the lock, then lock only around
the provider-switch mutation while preserving existing readiness and
legacy-primary conditions.
🪄 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: 97cd874c-2412-4919-a551-a3b33f189b77

📥 Commits

Reviewing files that changed from the base of the PR and between fa4e617 and 4bda1a8.

📒 Files selected for processing (24)
  • client/client.go
  • client/client_test.go
  • client/clients/tso/client.go
  • client/inner_client.go
  • client/servicediscovery/service_discovery.go
  • client/servicediscovery/tso_service_discovery.go
  • client/servicediscovery/tso_service_discovery_test.go
  • errors.toml
  • pkg/errs/errno.go
  • pkg/mcs/tso/server/server.go
  • pkg/mcs/utils/util.go
  • pkg/storage/endpoint/tso.go
  • pkg/storage/storage_tso_test.go
  • pkg/tso/allocator.go
  • pkg/tso/tso_test.go
  • pkg/utils/apiutil/serverapi/middleware.go
  • pkg/utils/apiutil/serverapi/middleware_test.go
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go
  • server/forward.go
  • server/grpc_service.go
  • server/grpc_service_test.go
  • server/server.go
  • tests/integrations/mcs/tso/server_test.go
✅ Files skipped from review due to trivial changes (1)
  • errors.toml

Comment thread server/cluster/cluster.go Outdated
Comment on lines +824 to +842
func (c *RaftCluster) switchTSOProviderToTSOIfServiceReady(allowLegacyPrimary, probeReady bool) error {
if c.IsServiceIndependent(constant.TSOServiceName) && !c.isTSOAllocatorInitialized() {
return nil
}
c.tsoSwitchMu.Lock()
defer c.tsoSwitchMu.Unlock()
if c.isKeyspaceGroupEnabled {
tsoServiceState, err := c.getDefaultTSOServiceDiscoveryState()
if err != nil {
return err
}
if tsoServiceState != tsoServiceDiscoveryReady &&
(!allowLegacyPrimary || tsoServiceState != tsoServiceDiscoveryLegacyPrimary) {
return nil
}
}
if probeReady && !c.isDefaultTSOServiceReady() {
return nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

sed -n '620,860p' server/cluster/cluster.go
printf '\n---\n'
rg -n "tsoSwitchMu|RunEmbeddedTSORequest|switchTSOProviderToPDIfNoTSOServiceLocked|switchTSOProviderToTSOIfServiceReady|getDefaultTSOServiceDiscoveryState|isDefaultTSOServiceReady|tsoServiceReadyCheckTimeout" server/cluster/cluster.go

Repository: tikv/pd

Length of output: 10461


🏁 Script executed:

sed -n '532,576p' server/cluster/cluster.go

Repository: tikv/pd

Length of output: 2120


🏁 Script executed:

sed -n '590,620p' server/cluster/cluster.go
printf '\n---\n'
rg -n "switchTSOProviderToTSOIfServiceReady\\(" -S .

Repository: tikv/pd

Length of output: 1511


Move the discovery/probe out from under tsoSwitchMu

checkTSOService already rechecks discovery before calling this helper, but switchTSOProviderToTSOIfServiceReady still takes the write lock and then does another etcd read and, on the legacy path, a 1s readiness probe. Because RunEmbeddedTSORequest takes tsoSwitchMu.RLock(), that can block embedded TSO requests for the full switch attempt. Read/probe first, then lock only to flip the provider.

🤖 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 `@server/cluster/cluster.go` around lines 824 - 842, Move the keyspace-group
discovery lookup and default TSO readiness probe out of the tsoSwitchMu critical
section in switchTSOProviderToTSOIfServiceReady: perform all etcd reads and
isDefaultTSOServiceReady checks before acquiring the lock, then lock only around
the provider-switch mutation while preserving existing readiness and
legacy-primary conditions.

Keep the current TSO provider unless service discovery confirms that no TSO server is registered. Classify timestamp fence conflicts so embedded PD TSO yields without resigning PD leadership.

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

ti-chi-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

@rleungx: The following tests 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-error-log-review 74617d2 link true /test pull-error-log-review
pull-unit-test-next-gen-2 74617d2 link true /test pull-unit-test-next-gen-2
pull-unit-test-next-gen-1 74617d2 link true /test pull-unit-test-next-gen-1
pull-unit-test-next-gen-3 74617d2 link true /test pull-unit-test-next-gen-3

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.

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/hold Indicates that a PR should not merge because someone has issued a /hold command. 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.

3 participants