Skip to content

br: set ratelimit for log restore (#64357) - #69153

Merged
ti-chi-bot[bot] merged 6 commits into
pingcap:release-8.5from
ti-chi-bot:cherry-pick-64357-to-release-8.5
Aug 3, 2026
Merged

ti-chi-bot[bot] merged 6 commits into
pingcap:release-8.5from
ti-chi-bot:cherry-pick-64357-to-release-8.5

Conversation

@ti-chi-bot

@ti-chi-bot ti-chi-bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Member

This is an automated cherry-pick of #64357 and #70221

What problem does this PR solve?

Issue Number: close #63505

Problem Summary: the download speed of log apply is not limited under the ratelimit

What changed and how does it work?

set rate limit for log restore

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

Please refer to Release Notes Language Style Guide to write a quality release note.

None

Summary by CodeRabbit

  • New Features

    • Added configurable download rate limiting for snapshot and SST restores.
    • Download limits automatically refresh during restore and reset after completion.
    • Online restores now avoid unnecessary import-mode switching.
    • Restore progress reports aggregated key-value, logical-size, and physical-size statistics.
  • Bug Fixes

    • Improved cancellation and cleanup handling during restore completion.
    • Ensured download-limit cleanup is safe to invoke multiple times.
    • Added expiration tracking to support reliable download-limit cleanup.

Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
@ti-chi-bot ti-chi-bot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. ok-to-test Indicates a PR is ready to be tested. release-note-none Denotes a PR that doesn't merit a release note. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. type/cherry-pick-for-release-8.5 This PR is cherry-picked to release-8.5 from a source PR. labels Jun 12, 2026
@ti-chi-bot ti-chi-bot mentioned this pull request Jun 12, 2026
2 of 13 tasks
@ti-chi-bot

Copy link
Copy Markdown
Member Author

@Leavrth This PR has conflicts, I have hold it.
Please resolve them or ask others to resolve them, then comment /unhold to remove the hold label.

@ti-chi-bot

ti-chi-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

@ti-chi-bot: ## If you want to know how to resolve it, please read the guide in TiDB Dev Guide.

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 ti-community-infra/tichi repository.

@ti-chi-bot ti-chi-bot Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jun 12, 2026
@coderabbitai

coderabbitai Bot commented Jun 12, 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 413cdb60-03eb-4cd9-87ce-c796325aa932

📥 Commits

Reviewing files that changed from the base of the PR and between 5d7f2dd and d32416e.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • DEPS.bzl
  • br/pkg/restore/import_mode_switcher_test.go
  • br/pkg/restore/log_client/client.go
  • br/pkg/restore/snap_client/BUILD.bazel
  • br/pkg/task/restore.go
  • br/pkg/task/stream.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (7)
  • go.mod
  • br/pkg/task/restore.go
  • DEPS.bzl
  • br/pkg/restore/snap_client/BUILD.bazel
  • br/pkg/task/stream.go
  • br/pkg/restore/import_mode_switcher_test.go
  • br/pkg/restore/log_client/client.go

📝 Walkthrough

Walkthrough

The PR updates online/offline restore mode handling and adds task-scoped SST download rate limiting. Snapshot and log restore clients now share callback-based rate-limit setup, periodic refresh, reset retries, and updated SST initialization.

Changes

Restore mode and online/offline flow

Layer / File(s) Summary
Restore mode flow and validation
br/pkg/restore/import_mode_switcher.go, br/pkg/task/restore.go, br/pkg/task/stream.go, br/pkg/restore/log_client/client.go, br/pkg/restore/import_mode_switcher_test.go
Pre-work uses the revised signature. SST restoration skips import-mode transitions for online restores. Post-work restores schedulers without switching to normal mode online. Tests validate switch behavior.

Importer metadata and rate-limit lifecycle

Layer / File(s) Summary
Task-scoped download limits
br/pkg/restore/snap_client/import.go, br/pkg/restore/snap_client/import_test.go
Each importer sends a generated task ID and a 3600-second TTL with download speed-limit requests. Tests validate initial and reset requests.
Rate-limit callbacks
br/pkg/restore/snap_client/client.go, br/pkg/restore/snap_client/client_test.go, br/pkg/restore/snap_client/export_test.go, br/pkg/restore/snap_client/BUILD.bazel
Speed limits use PD-discovered stores and a worker pool. Open callbacks refresh limits periodically. Close callbacks stop refresh and retry reset operations.

LogClient SST integration

Layer / File(s) Summary
SST restore initialization
br/pkg/restore/log_client/client.go, br/pkg/task/stream.go, DEPS.bzl, go.mod
LogClient accepts rate limits and online mode, creates the SST worker pool externally, wires snapshot callbacks, and initializes the selected restorer. SST statistics are aggregated before logging. The kvproto dependency metadata is updated.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RestoreTask
  participant LogClient
  participant SnapClient
  participant SnapFileImporter
  participant PD
  participant TiKV
  RestoreTask->>LogClient: pass online mode and rate limit
  LogClient->>SnapClient: register rate-limit callbacks
  SnapClient->>SnapFileImporter: open importer
  SnapClient->>PD: fetch TiKV stores
  PD-->>SnapClient: return stores
  SnapClient->>TiKV: apply task-scoped speed limit
  SnapClient->>SnapFileImporter: close importer
  SnapClient->>TiKV: reset speed limit with retries
Loading

Possibly related PRs

  • pingcap/tidb#69590: Both modify SST/log restore orchestration and concurrency or configuration plumbing.
  • pingcap/tidb#70221: Both extend online/offline import-mode handling in restore paths.

Suggested reviewers: ridrisr, yujuncen

Poem

A rabbit sets the rate just right,
Each task carries its tag in flight.
Online restores skip mode change,
Callbacks refresh across the range.
SST totals hop into sight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.32% 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
Title check ✅ Passed The title clearly summarizes the primary change: applying a rate limit to log restore.
Description check ✅ Passed The description includes the issue, problem, change, tests, side effects, documentation, and release note sections.
Linked Issues check ✅ Passed The changes configure log restore rate limiting and apply it to SST download operations, meeting issue #63505.
Out of Scope Changes check ✅ Passed The supporting import-mode, callback, dependency, and test changes are related to implementing and validating log restore rate limiting.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


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.

@tiprow

tiprow Bot commented Jun 12, 2026

Copy link
Copy Markdown

@ti-chi-bot: 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
fast_test_tiprow_for_release f4d7e78 link true /test fast_test_tiprow_for_release

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.

@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

Caution

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

⚠️ Outside diff range comments (1)
br/pkg/restore/snap_client/client.go (1)

799-827: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Resolve the cherry-pick conflicts across the restore rate-limit path.

These hunks in br/pkg/restore/snap_client/client.go and br/pkg/restore/log_client/client.go still contain unresolved conflict markers, so the branch will not compile. When you keep the newer InitClients path in br/pkg/restore/log_client/client.go, also rename snapFileImporter back to the in-scope fileImporter.

🤖 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 `@br/pkg/restore/snap_client/client.go` around lines 799 - 827, Remove the
unresolved git conflict markers and pick the newer rate-limit implementation:
replace the old SetSpeedLimitFn block with the SetSpeedLimitCallbacks call (use
SetSpeedLimitCallbacks(ctx, rc.pdClient, rc.workerPool, rc.rateLimit) to produce
createCallBack and closeCallBack and append them to
createCallBacks/closeCallBacks), remove the retry/reset loop variant, and ensure
you rename any local variable snapFileImporter back to the in-scope fileImporter
to match the InitClients path in log_client (also remove the conflict markers
<<<<<<</=======/>>>>>>>).
🧹 Nitpick comments (3)
br/pkg/restore/import_mode_switcher_test.go (1)

51-138: ⚡ Quick win

Keep a regression test for the online no-op path.

RestorePreWork still has a live isOnline early-return branch, and br/pkg/task/restore.go plus br/pkg/task/restore_raw.go still rely on it. With RestorePostWork now always running, removing the online-path test leaves the “no import-mode switch / no scheduler restore needed” contract unverified.

As per coding guidelines, "Test files: Prefer extending existing test suites and fixtures over creating new scaffolding; keep test changes minimal and deterministic."

🤖 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 `@br/pkg/restore/import_mode_switcher_test.go` around lines 51 - 138, Add a
deterministic regression test that exercises the early-return "online" path of
RestorePreWork and verifies RestorePostWork is a no-op: call
restore.RestorePreWork with the isOnline=true flag (using the existing test
fixture setup: mgr, switcher, pdHTTPCli), assert that it returns a nil/empty
cfg/undo (or otherwise indicates no scheduler changes), confirm pdHTTPCli and
pdutil scheduler state is unchanged, then call restore.RestorePostWork(switcher,
undo) and re-check pdHTTPCli/pdutil remain unchanged; place this in
import_mode_switcher_test.go alongside TestRestorePreWork to reuse existing
setup and keep the test minimal and deterministic.

Source: Coding guidelines

br/pkg/restore/snap_client/import.go (1)

80-80: ⚡ Quick win

Add doc comments for the newly exported rate-limit APIs.

DownloadRateLimitTTLSeconds, SetSpeedLimitCallbacks, SetSpeedLimitFn, and SetRateLimit are all newly exported; please add package-style doc comments that explain their constraints and intent.

As per coding guidelines, "Comments SHOULD explain non-obvious intent, constraints, invariants, concurrency guarantees, SQL/compatibility contracts, or important performance trade-offs" and "Keep exported-symbol doc comments, and prefer semantic constraints over name restatement."

🤖 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 `@br/pkg/restore/snap_client/import.go` at line 80, Add package-style doc
comments for the newly exported symbols DownloadRateLimitTTLSeconds,
SetSpeedLimitCallbacks, SetSpeedLimitFn, and SetRateLimit: describe the units
and purpose of DownloadRateLimitTTLSeconds (seconds, TTL for cached rate
limits), specify expected behavior and thread-safety/locking assumptions for
SetSpeedLimitCallbacks and SetSpeedLimitFn (what callbacks/signatures are
invoked, whether they may be called concurrently, and if they must be
non-blocking), and document SetRateLimit’s contract (valid range/units for rate
values, effect on existing transfers, and how TTL interacts with explicit sets).
Keep comments short, state constraints/invariants, and use package-style
sentences above each exported declaration.

Source: Coding guidelines

br/pkg/restore/snap_client/client_test.go (1)

428-471: 💤 Low value

Good idempotency test, consider adding a doc comment.

The test correctly verifies that closeCallBack can be called multiple times without blocking or erroring, even after context cancellation. Consider adding a brief comment at the start of the test explaining this intent for future readers.

📝 Suggested doc comment
 func TestSetSpeedLimitCloseCallbackIdempotent(t *testing.T) {
+	// Verify that the close callback returned by SetSpeedLimitCallbacks is idempotent
+	// and can be safely called multiple times without blocking or error.
 	mockStores := []*metapb.Store{
🤖 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 `@br/pkg/restore/snap_client/client_test.go` around lines 428 - 471, Add a
brief doc comment at the top of TestSetSpeedLimitCloseCallbackIdempotent that
explains the test verifies idempotency and non-blocking behavior of the
closeCallBack (after context cancellation) and that calling closeCallBack
multiple times should return quickly without error; place the comment
immediately above the TestSetSpeedLimitCloseCallbackIdempotent function and
mention the relevant symbols createCallBack and closeCallBack so readers know
the test's intent.
🤖 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 `@br/pkg/restore/snap_client/client.go`:
- Around line 693-745: The refresh goroutine uses the long-lived ctx for setFn
calls and can block shutdown; modify the code so the ticker loop creates a
bounded/cancelable child context for each setFn call (e.g. ctxRefresh, cancel :=
context.WithTimeout(ctx, refreshCallTimeout)) and pass ctxRefresh to
setFn(importer, rateLimit), deferring cancel immediately after the call, and
also have an outer cancel (ctxLoopCancel) created with context.WithCancel(ctx)
that's stored outside the goroutine; in the close callback (the second returned
func) call ctxLoopCancel() (or cancel) before closing stopCh and wg.Wait() to
ensure any in-flight setFn calls are canceled and the goroutine can exit
promptly; reference SetSpeedLimitFn, setFn, SnapFileImporter, stopCh, stopOnce,
wg, updateTicker and ctx when locating changes.

---

Outside diff comments:
In `@br/pkg/restore/snap_client/client.go`:
- Around line 799-827: Remove the unresolved git conflict markers and pick the
newer rate-limit implementation: replace the old SetSpeedLimitFn block with the
SetSpeedLimitCallbacks call (use SetSpeedLimitCallbacks(ctx, rc.pdClient,
rc.workerPool, rc.rateLimit) to produce createCallBack and closeCallBack and
append them to createCallBacks/closeCallBacks), remove the retry/reset loop
variant, and ensure you rename any local variable snapFileImporter back to the
in-scope fileImporter to match the InitClients path in log_client (also remove
the conflict markers <<<<<<</=======/>>>>>>>).

---

Nitpick comments:
In `@br/pkg/restore/import_mode_switcher_test.go`:
- Around line 51-138: Add a deterministic regression test that exercises the
early-return "online" path of RestorePreWork and verifies RestorePostWork is a
no-op: call restore.RestorePreWork with the isOnline=true flag (using the
existing test fixture setup: mgr, switcher, pdHTTPCli), assert that it returns a
nil/empty cfg/undo (or otherwise indicates no scheduler changes), confirm
pdHTTPCli and pdutil scheduler state is unchanged, then call
restore.RestorePostWork(switcher, undo) and re-check pdHTTPCli/pdutil remain
unchanged; place this in import_mode_switcher_test.go alongside
TestRestorePreWork to reuse existing setup and keep the test minimal and
deterministic.

In `@br/pkg/restore/snap_client/client_test.go`:
- Around line 428-471: Add a brief doc comment at the top of
TestSetSpeedLimitCloseCallbackIdempotent that explains the test verifies
idempotency and non-blocking behavior of the closeCallBack (after context
cancellation) and that calling closeCallBack multiple times should return
quickly without error; place the comment immediately above the
TestSetSpeedLimitCloseCallbackIdempotent function and mention the relevant
symbols createCallBack and closeCallBack so readers know the test's intent.

In `@br/pkg/restore/snap_client/import.go`:
- Line 80: Add package-style doc comments for the newly exported symbols
DownloadRateLimitTTLSeconds, SetSpeedLimitCallbacks, SetSpeedLimitFn, and
SetRateLimit: describe the units and purpose of DownloadRateLimitTTLSeconds
(seconds, TTL for cached rate limits), specify expected behavior and
thread-safety/locking assumptions for SetSpeedLimitCallbacks and SetSpeedLimitFn
(what callbacks/signatures are invoked, whether they may be called concurrently,
and if they must be non-blocking), and document SetRateLimit’s contract (valid
range/units for rate values, effect on existing transfers, and how TTL interacts
with explicit sets). Keep comments short, state constraints/invariants, and use
package-style sentences above each exported declaration.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 38c3818e-58f7-4bbc-b675-1185750a10ab

📥 Commits

Reviewing files that changed from the base of the PR and between ef954aa and f4d7e78.

📒 Files selected for processing (14)
  • br/pkg/restore/BUILD.bazel
  • br/pkg/restore/import_mode_switcher.go
  • br/pkg/restore/import_mode_switcher_test.go
  • br/pkg/restore/log_client/client.go
  • br/pkg/restore/snap_client/BUILD.bazel
  • br/pkg/restore/snap_client/client.go
  • br/pkg/restore/snap_client/client_test.go
  • br/pkg/restore/snap_client/export_test.go
  • br/pkg/restore/snap_client/import.go
  • br/pkg/restore/snap_client/import_test.go
  • br/pkg/task/restore.go
  • br/pkg/task/restore_raw.go
  • br/pkg/task/restore_txn.go
  • br/pkg/task/stream.go

Comment on lines +693 to +745
var wg sync.WaitGroup
stopCh := make(chan struct{})
var stopOnce sync.Once
setFn := SetSpeedLimitFn(ctx, pdClient, pool)
return func(importer *SnapFileImporter) error {
if err := setFn(importer, rateLimit); err != nil {
return errors.Annotate(err, "failed to set download speed limit")
}
wg.Add(1)
go func() {
defer wg.Done()
updateTicker := time.NewTicker(time.Minute * 3)
defer updateTicker.Stop()
for {
select {
case <-ctx.Done():
return
case <-updateTicker.C:
if err := setFn(importer, rateLimit); err != nil {
log.Warn("failed to set download speed limit, retry it", zap.Error(err))
}
case <-stopCh:
return
}
}
}()
return nil
}, func(importer *SnapFileImporter) error {
stopOnce.Do(func() {
close(stopCh)
})
wg.Wait()

// In future we may need a mechanism to set speed limit in ttl. like what we do in switchmode. TODO
var resetErr error
for retry := range resetSpeedLimitRetryTimes {
resetCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), resetSpeedLimitTimeout)
resetErr = SetSpeedLimitFn(resetCtx, pdClient, pool)(importer, 0)
cancel()
if resetErr != nil {
log.Warn("failed to reset speed limit, retry it",
zap.Int("retry time", retry), logutil.ShortError(resetErr))
time.Sleep(time.Duration(retry+3) * time.Second)
continue
}
break
}
if resetErr != nil {
log.Error("failed to reset speed limit, please reset it manually", zap.Error(resetErr))
}
return resetErr
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Close can hang behind an in-flight refresh.

The ticker goroutine runs setFn with the long-lived restore context, but the close callback only closes stopCh and then waits on wg. If PD lookup or any SetDownloadSpeedLimit RPC stalls while that context is still alive, the goroutine never gets back to the select, and importer shutdown blocks indefinitely. Give the refresh loop its own cancelable/timeout-bounded context and cancel it before wg.Wait().

🤖 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 `@br/pkg/restore/snap_client/client.go` around lines 693 - 745, The refresh
goroutine uses the long-lived ctx for setFn calls and can block shutdown; modify
the code so the ticker loop creates a bounded/cancelable child context for each
setFn call (e.g. ctxRefresh, cancel := context.WithTimeout(ctx,
refreshCallTimeout)) and pass ctxRefresh to setFn(importer, rateLimit),
deferring cancel immediately after the call, and also have an outer cancel
(ctxLoopCancel) created with context.WithCancel(ctx) that's stored outside the
goroutine; in the close callback (the second returned func) call ctxLoopCancel()
(or cancel) before closing stopCh and wg.Wait() to ensure any in-flight setFn
calls are canceled and the goroutine can exit promptly; reference
SetSpeedLimitFn, setFn, SnapFileImporter, stopCh, stopOnce, wg, updateTicker and
ctx when locating changes.

Signed-off-by: Jianjun Liao <jianjun.liao@outlook.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 Jun 26, 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.

🧹 Nitpick comments (1)
br/pkg/restore/log_client/client.go (1)

559-560: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Use a dedicated pool for speed-limit callbacks.

SetSpeedLimitCallbacks periodically reapplies and later resets the limit through the pool passed at Line 560, while the same sstWorkerPool is consumed by SST restore work at Lines 584 and 587. If restore work saturates that pool, the refresh/reset RPCs can queue behind data restore tasks, letting the configured limit expire or delaying cleanup. Consider a small control-plane pool sized by store count.

Proposed direction
 	if rc.rateLimit != 0 {
-		createCallBack, closeCallBack := snapclient.SetSpeedLimitCallbacks(ctx, rc.pdClient, sstWorkerPool, rc.rateLimit)
+		speedLimitPoolSize := uint(len(stores))
+		if speedLimitPoolSize == 0 {
+			speedLimitPoolSize = 1
+		}
+		speedLimitWorkerPool := tidbutil.NewWorkerPool(speedLimitPoolSize, "sst speed limit")
+		createCallBack, closeCallBack := snapclient.SetSpeedLimitCallbacks(ctx, rc.pdClient, speedLimitWorkerPool, rc.rateLimit)
 		createCallBacks = append(createCallBacks, createCallBack)
 		closeCallBacks = append(closeCallBacks, closeCallBack)
 	}

Also applies to: 582-587

🤖 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 `@br/pkg/restore/log_client/client.go` around lines 559 - 560, The speed-limit
callback scheduling in rc.rateLimit setup is using the same sstWorkerPool as SST
restore work, which can let refresh/reset RPCs get blocked behind data transfer
tasks. Update the SetSpeedLimitCallbacks call in client.go to use a dedicated
small control-plane pool instead of sstWorkerPool, and wire that pool through
the restore path where SST work is started so callback reapply/reset operations
stay responsive even under heavy restore load.
🤖 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 `@br/pkg/restore/log_client/client.go`:
- Around line 559-560: The speed-limit callback scheduling in rc.rateLimit setup
is using the same sstWorkerPool as SST restore work, which can let refresh/reset
RPCs get blocked behind data transfer tasks. Update the SetSpeedLimitCallbacks
call in client.go to use a dedicated small control-plane pool instead of
sstWorkerPool, and wire that pool through the restore path where SST work is
started so callback reapply/reset operations stay responsive even under heavy
restore load.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 60c6a331-2fdc-4fd2-9f4e-15f8932a1369

📥 Commits

Reviewing files that changed from the base of the PR and between f4d7e78 and c946172.

📒 Files selected for processing (2)
  • br/pkg/restore/log_client/client.go
  • br/pkg/restore/snap_client/client.go
💤 Files with no reviewable changes (1)
  • br/pkg/restore/snap_client/client.go

@ti-chi-bot ti-chi-bot Bot added cherry-pick-approved Cherry pick PR approved by release team. and removed do-not-merge/cherry-pick-not-approved labels Jul 31, 2026
@ti-chi-bot

Copy link
Copy Markdown
Member Author

Cherry-pick conflicts appear resolved; removing the do-not-merge/hold label.

@ti-chi-bot ti-chi-bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 3, 2026
@ti-chi-bot ti-chi-bot Bot added approved needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Aug 3, 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 `@br/pkg/restore/import_mode_switcher.go`:
- Around line 247-250: Update the canceled-context handling in RestorePostWork
so post-work cleanup uses a finite timeout context rather than unbounded
context.Background(). Apply that bounded context to both SwitchToNormalMode and
restoreSchedulers, preserving the existing cancellation behavior and ensuring
the timeout context is released after cleanup.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f2acabf3-52c0-470f-a178-371f0217c9ca

📥 Commits

Reviewing files that changed from the base of the PR and between c946172 and 139c5f7.

📒 Files selected for processing (5)
  • br/pkg/restore/import_mode_switcher.go
  • br/pkg/restore/import_mode_switcher_test.go
  • br/pkg/restore/log_client/client.go
  • br/pkg/task/restore.go
  • br/pkg/task/stream.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • br/pkg/restore/log_client/client.go

Comment on lines 247 to 250
if ctx.Err() != nil {
log.Warn("context canceled, try shutdown")
ctx = context.Background()
}

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 | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect context propagation and retry behavior in cleanup operations.
rg -n -A80 -B10 'func \(switcher \*ImportModeSwitcher\) switchTiKVMode|func \(switcher \*ImportModeSwitcher\) SwitchToNormalMode' \
  br/pkg/restore/import_mode_switcher.go

# Locate scheduler undo implementations and inspect their context handling.
rg -n -A40 -B10 'func .*MakeUndoFunctionByConfig|func .*RemoveSchedulersWithConfig|type UndoFunc' br/pkg

Repository: pingcap/tidb

Length of output: 14690


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the exact context cleanup path and surrounding deferred undo context.
sed -n '220,265p' br/pkg/restore/import_mode_switcher.go

# Inspect scheduler restore implementation and context handling.
sed -n '620,725p' br/pkg/pdutil/pd.go

# Search for callers of restore deferred cleanup to see whether a timeout is already applied later.
rg -n -A20 -B20 'defer .*undo|defer.*\.Apply|RemoveSchedulers\(ctx\)|RestoreSchedulers' br/pkg/restore br/pkg/lightning br/pkg

Repository: pingcap/tidb

Length of output: 20458


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the full relevant import mode switcher cleanup path.
sed -n '1,90p' br/pkg/restore/import_mode_switcher.go
sed -n '230,255p' br/pkg/restore/import_mode_switcher.go

# Read scheduler restore implementation and helper request behavior.
sed -n '660,730p' br/pkg/pdutil/pd.go

# Inspect how pdcontroller request methods pass the context.
rg -n -A30 'func \(p \*PdController\) (GetAllStores|GetPDScheduleConfig|ListSchedulers|UpdatePDScheduleConfig|putPDScheduleConfig|doUpdatePDScheduleConfig|getPDScheduleConfig)' br/pkg/pdutil/pd.go

Repository: pingcap/tidb

Length of output: 7877


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read scheduler resume and remaining restore path after scheduling.
sed -n '730,790p' br/pkg/pdutil/pd.go

Repository: pingcap/tidb

Length of output: 2695


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the implementation that resumes schedulers and how the generated undo calls the restore path.
sed -n '396,435p' br/pkg/pdutil/pd.go
sed -n '330,365p' br/pkg/pdutil/pd.go
sed -n '465,484p' br/pkg/pdutil/pd.go

Repository: pingcap/tidb

Length of output: 3773


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the scheduler resume implementation and the remaining restoreSchedulers tail.
sed -n '300,370p' br/pkg/pdutil/pd.go
sed -n '734,780p' br/pkg/pdutil/pd.go

Repository: pingcap/tidb

Length of output: 4701


Bound the post-work cleanup context.

RestorePostWork replaces a canceled ctx with an unbounded context.Background() before calling SwitchToNormalMode and restoreSchedulers. Both paths can make remote PD/TiKV requests. Apply a finite timeout to these cleanup calls so an unavailable endpoint cannot block restore completion indefinitely.

🤖 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 `@br/pkg/restore/import_mode_switcher.go` around lines 247 - 250, Update the
canceled-context handling in RestorePostWork so post-work cleanup uses a finite
timeout context rather than unbounded context.Background(). Apply that bounded
context to both SwitchToNormalMode and restoreSchedulers, preserving the
existing cancellation behavior and ensuring the timeout context is released
after cleanup.

@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Aug 3, 2026
@ti-chi-bot

ti-chi-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-08-03 07:47:08.132672814 +0000 UTC m=+2427814.168767870: ☑️ agreed by YuJuncen.
  • 2026-08-03 08:04:31.162856138 +0000 UTC m=+2428857.198951204: ☑️ agreed by RidRisR.

Signed-off-by: Jianjun Liao <jianjun.liao@outlook.com>
@ti-chi-bot

ti-chi-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: RidRisR, YuJuncen

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

@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 `@DEPS.bzl`:
- Around line 5987-5993: Update the com_github_pingcap_kvproto archive
declaration in DEPS.bzl by adding a reachable public Go module proxy URL to the
fallback list, replacing or removing the 404ing
storage.googleapis.com/pingcapmirror URL as appropriate. Verify that the sha256
value matches the archive served for version v0.0.0-20260803062813-07aa8c6a46fa,
while preserving the existing internal mirrors.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: caa8f054-c2d8-4c71-b4d6-66cee954aa66

📥 Commits

Reviewing files that changed from the base of the PR and between 139c5f7 and 5d7f2dd.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • DEPS.bzl
  • go.mod

Comment thread DEPS.bzl Outdated
@codecov

codecov Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 64.86486% with 39 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (release-8.5@4f4bc88). Learn more about missing BASE report.

Additional details and impacted files
@@               Coverage Diff                @@
##             release-8.5     #69153   +/-   ##
================================================
  Coverage               ?   55.7791%           
================================================
  Files                  ?       1849           
  Lines                  ?     666891           
  Branches               ?          0           
================================================
  Hits                   ?     371986           
  Misses                 ?     267264           
  Partials               ?      27641           
Flag Coverage Δ
integration 39.3254% <63.0630%> (?)
unit 65.2039% <33.3333%> (?)

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

Components Coverage Δ
dumpling 55.3108% <0.0000%> (?)
parser ∅ <0.0000%> (?)
br 63.0698% <0.0000%> (?)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Leavrth

Leavrth commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

/test unit-test

1 similar comment
@Leavrth

Leavrth commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

/test unit-test

@Leavrth

Leavrth commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

/test check_dev_2

@ti-chi-bot

ti-chi-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

@Leavrth: The specified target(s) for /test were not found.
The following commands are available to trigger required jobs:

/test build
/test check-dev
/test check-dev2
/test mysql-test
/test pull-br-integration-test
/test pull-unit-test-ddlv1
/test unit-test

The following commands are available to trigger optional jobs:

/test pull-check-deps
/test pull-common-test
/test pull-e2e-test
/test pull-integration-common-test
/test pull-integration-copr-test
/test pull-integration-ddl-test
/test pull-integration-e2e-test
/test pull-integration-jdbc-test
/test pull-integration-mysql-test
/test pull-integration-nodejs-test
/test pull-integration-python-orm-test
/test pull-integration-tidb-tools-test
/test pull-lightning-integration-test
/test pull-mysql-client-test
/test pull-sqllogic-test

Use /test all to run the following jobs that were automatically triggered:

pingcap/tidb/release-8.5/pull_br_integration_test
pingcap/tidb/release-8.5/pull_build
pingcap/tidb/release-8.5/pull_check
pingcap/tidb/release-8.5/pull_check2
pingcap/tidb/release-8.5/pull_mysql_test
pingcap/tidb/release-8.5/pull_unit_test
pull-check-deps
Details

In response to this:

/test check_dev_2

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.

@Leavrth

Leavrth commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

/test check-dev2

@Leavrth

Leavrth commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

/retest

@Leavrth

Leavrth commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

/test pull-br-integration-test

@ti-chi-bot
ti-chi-bot Bot merged commit e50165e into pingcap:release-8.5 Aug 3, 2026
20 checks passed
@ti-chi-bot
ti-chi-bot Bot deleted the cherry-pick-64357-to-release-8.5 branch August 3, 2026 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved cherry-pick-approved Cherry pick PR approved by release team. lgtm ok-to-test Indicates a PR is ready to be tested. release-note-none Denotes a PR that doesn't merit a release note. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. type/cherry-pick-for-release-8.5 This PR is cherry-picked to release-8.5 from a source PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants