Skip to content

config: persist default store limit for future stores - #10900

Open
King-Dylan wants to merge 4 commits into
tikv:masterfrom
King-Dylan:persist-default-store-limit
Open

config: persist default store limit for future stores#10900
King-Dylan wants to merge 4 commits into
tikv:masterfrom
King-Dylan:persist-default-store-limit

Conversation

@King-Dylan

@King-Dylan King-Dylan commented Jun 15, 2026

Copy link
Copy Markdown

What problem does this PR solve?

Issue Number: close #10898

Persist the default store limit used for future stores. Today /pd/api/v1/stores/limit updates existing stores and mutates the process-local default store limit, but the default for future stores is not persisted. After PD/API/scheduling service restart or leader/primary switch, newly joined TiKV stores can fall back to the built-in default value.

What is changed and how does it work?

  • Add schedule.default-store-limit to ScheduleConfig.
  • Update SetAllStoresLimit to persist the default limit as well as updating existing per-store entries.
  • Initialize missing/new store limits from persisted schedule.default-store-limit before falling back to the process default.
  • Keep per-store schedule.store-limit[storeID] as the highest-priority override.
  • Keep the current TiFlash default store limit behavior unchanged.
  • Apply the same default-store-limit logic to MCS scheduling PersistConfig.

The resulting priority is:

  1. per-store schedule.store-limit[storeID]
  2. persisted schedule.default-store-limit
  3. process default

Check List

Tests

  • Unit test
go test ./pkg/schedule/config ./server/config ./pkg/mcs/scheduling/server/config ./server/cluster -run 'Test(DefaultStoreLimitAdjust|ReloadDefaultStoreLimit|PersistConfigDefaultStoreLimit|AddStoreLimitUsesPersistedDefaultStoreLimit|StoreLimitChangeRefreshLimiter)'

Also attempted the existing MCS integration store-limit test:

cd tests/integrations
go test ./mcs/scheduling -run 'TestServerTestSuite/TestStoreLimit'

It failed during build because dashboard embedded assets were not generated in this checkout:

../../pkg/dashboard/uiserver/embedded_assets_rewriter.go:36:26: undefined: assets
../../pkg/dashboard/uiserver/embedded_assets_rewriter.go:37:13: undefined: vfsgen۰FS
../../pkg/dashboard/uiserver/embedded_assets_rewriter.go:39:15: undefined: vfsgen۰CompressedFileInfo
../../pkg/dashboard/uiserver/embedded_assets_rewriter.go:47:9: undefined: assets

Code changes

  • Has configuration change

Side effects

  • No known side effects

Release note

PD now persists store limit defaults set by the stores limit API, so new TiKV stores consistently inherit the configured default after leader switches or restarts.

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Store limit defaults for adding and removing peers now consistently use persisted schedule settings, including after a restart.
    • Reloading and adjusting schedules now preserves configured default values, including explicit zero values and engine-specific defaults.
    • Per-store overrides are retained while updating only the selected limit type.
    • Deprecated store-balance settings are migrated more reliably, filling missing defaults without overwriting explicitly configured values.

@ti-chi-bot ti-chi-bot Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. do-not-merge/needs-triage-completed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. contribution This PR is from a community contributor. needs-ok-to-test Indicates a PR created by contributors and need ORG member send '/ok-to-test' to start testing. dco-signoff: no Indicates the PR's author has not signed dco. labels Jun 15, 2026
@coderabbitai

coderabbitai Bot commented Jun 15, 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

This PR adds persisted schedule-level default store limits. Store-limit read and write paths now use the persisted defaults. Tests cover adjustment, migration, reload, restart, per-store overrides, and future-store initialization.

Changes

Persisted default store limit flow

Layer / File(s) Summary
Schedule default store-limit contract
pkg/schedule/config/config.go
ScheduleConfig stores default-store-limit, adjusts missing values, migrates StoreBalanceRate, and exposes effective default-limit helpers.
Store-limit persistence and cluster usage
server/config/persist_options.go, pkg/mcs/scheduling/server/config/config.go, server/cluster/cluster.go
Store-limit setters and getters use schedule-level defaults. Cluster store initialization and rollback use the cloned configuration values.
Restart and reload coverage
pkg/mcs/scheduling/server/config/config_test.go, server/config/config_test.go, server/cluster/cluster_test.go
Tests cover persistence, reload, explicit zero values, per-store overrides, deprecated migration, simulated restart, and future-store initialization.

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

Suggested reviewers: lhy1024, rleungx, bufferflies

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% 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 and concisely describes persisting default store limits for future stores.
Description check ✅ Passed The description covers the problem, issue, implementation, precedence, tests, known build limitation, configuration change, and release note.
Linked Issues check ✅ Passed The changes satisfy issue #10898 by persisting defaults, preserving precedence, handling restarts, and covering MCS scheduling.
Out of Scope Changes check ✅ Passed All production and test changes directly support persisted default store limits and the linked issue objectives.
✨ 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.

@ti-chi-bot

ti-chi-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Hi @King-Dylan. Thanks for your PR.

I'm waiting for a tikv member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

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.

@ti-chi-bot ti-chi-bot Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Jun 15, 2026
@King-Dylan
King-Dylan force-pushed the persist-default-store-limit branch from b2c0925 to 62c341f Compare June 15, 2026 21:53
@ti-chi-bot ti-chi-bot Bot added dco-signoff: yes Indicates the PR's author has signed the dco. and removed dco-signoff: no Indicates the PR's author has not signed dco. labels Jun 15, 2026
@King-Dylan
King-Dylan marked this pull request as ready for review June 16, 2026 17:28
@ti-chi-bot ti-chi-bot Bot removed do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. do-not-merge/needs-triage-completed labels Jun 16, 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 `@pkg/schedule/config/config.go`:
- Around line 633-641: The GetDefaultStoreLimit method treats any zero value as
unset and replaces it with process defaults, which breaks persistence of
explicitly configured zero values across restart. Replace the zero-value checks
for AddPeer and RemovePeer fields with a proper mechanism to distinguish between
explicitly set zero values and truly unset values (such as using pointers to the
fields or a different storage representation), so that persisted zero values are
respected and not overwritten by process defaults.
🪄 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: cfc073c5-d240-4769-8674-03ba34dcad72

📥 Commits

Reviewing files that changed from the base of the PR and between 1d3e90f and 62c341f.

📒 Files selected for processing (7)
  • pkg/mcs/scheduling/server/config/config.go
  • pkg/mcs/scheduling/server/config/config_test.go
  • pkg/schedule/config/config.go
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go
  • server/config/config_test.go
  • server/config/persist_options.go

Comment thread pkg/schedule/config/config.go Outdated
@King-Dylan
King-Dylan force-pushed the persist-default-store-limit branch 2 times, most recently from 5e152da to 6f224a3 Compare June 25, 2026 21:02

@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 `@pkg/schedule/config/config.go`:
- Around line 472-475: The migration logic in config.go currently lets
StoreBalanceRate overwrite an explicitly configured
DefaultStoreLimit/DefaultStoreLimitConfig, which clobbers user-specified
add-peer/remove-peer values. Update the backfill path around StoreBalanceRate
handling so it only populates DefaultStoreLimit when the corresponding
default-store-limit fields are unset, or add explicit validation to reject mixed
configuration; use the existing config migration logic in the affected blocks
near the StoreBalanceRate assignments and the
DefaultStoreLimit/DefaultStoreLimitConfig fields to preserve explicit values.
🪄 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: 2749e8c6-be72-4a19-b949-c6a6e8ff6353

📥 Commits

Reviewing files that changed from the base of the PR and between 5e152da and 6f224a3.

📒 Files selected for processing (7)
  • pkg/mcs/scheduling/server/config/config.go
  • pkg/mcs/scheduling/server/config/config_test.go
  • pkg/schedule/config/config.go
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go
  • server/config/config_test.go
  • server/config/persist_options.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • server/config/persist_options.go
  • pkg/mcs/scheduling/server/config/config.go
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go

Comment thread pkg/schedule/config/config.go Outdated
Close tikv#10898

Signed-off-by: King-Dylan <702299521@qq.com>
@King-Dylan
King-Dylan force-pushed the persist-default-store-limit branch from 6f224a3 to 9a3351f Compare June 29, 2026 18:08
@ti-chi-bot ti-chi-bot Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Jun 29, 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.

♻️ Duplicate comments (1)
pkg/schedule/config/config.go (1)

509-511: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Don't use a zero StoreLimitConfig as the nil-meta sentinel.

Line 509 still conflates an explicit default-store-limit = {add-peer: 0, remove-peer: 0} with “unset”. When MigrateDeprecatedFlags hits this nil-metadata path on Line 571, store-balance-rate will overwrite that explicit default and violate the new precedence contract. This branch needs presence tracking (or mixed-config rejection) too.

Also applies to: 571-571

🤖 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/schedule/config/config.go` around lines 509 - 511, The DefaultStoreLimit
handling in config migration is using an all-zero StoreLimitConfig as the unset
sentinel, which incorrectly treats an explicit default-store-limit of zeros as
missing. Update the logic in the config migration path around DefaultStoreLimit
and MigrateDeprecatedFlags to track whether the field was actually present (or
reject mixed configs) instead of relying on zero-value comparison, so
store-balance-rate does not overwrite an explicit default and the precedence
rules remain intact.
🧹 Nitpick comments (1)
pkg/mcs/scheduling/server/config/config_test.go (1)

46-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Round-trip the config for the restart assertion.

Line 46 says this simulates a restarted process, but Lines 47-49 still read from the same persistConfig instance. That only proves the in-memory precedence order; it will not catch a persistence/reload regression in default-store-limit. Rebuild PersistConfig from persisted state before the last assertion so this test actually covers the restart contract from the PR objective.

🤖 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/mcs/scheduling/server/config/config_test.go` around lines 46 - 49, The
restart assertion in the config test is still using the same in-memory
PersistConfig instance, so it does not verify the persisted round-trip behavior.
Rebuild a new PersistConfig from the saved state before the final GetStoreLimit
assertion, using the existing DefaultStoreLimit setup to simulate a real process
restart. Keep the assertion against StoreLimitConfig but make it exercise the
reload path rather than only the precedence order.
🤖 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.

Duplicate comments:
In `@pkg/schedule/config/config.go`:
- Around line 509-511: The DefaultStoreLimit handling in config migration is
using an all-zero StoreLimitConfig as the unset sentinel, which incorrectly
treats an explicit default-store-limit of zeros as missing. Update the logic in
the config migration path around DefaultStoreLimit and MigrateDeprecatedFlags to
track whether the field was actually present (or reject mixed configs) instead
of relying on zero-value comparison, so store-balance-rate does not overwrite an
explicit default and the precedence rules remain intact.

---

Nitpick comments:
In `@pkg/mcs/scheduling/server/config/config_test.go`:
- Around line 46-49: The restart assertion in the config test is still using the
same in-memory PersistConfig instance, so it does not verify the persisted
round-trip behavior. Rebuild a new PersistConfig from the saved state before the
final GetStoreLimit assertion, using the existing DefaultStoreLimit setup to
simulate a real process restart. Keep the assertion against StoreLimitConfig but
make it exercise the reload path rather than only the precedence order.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1c6f7271-2f64-4a84-b26c-57c8b9f93e4b

📥 Commits

Reviewing files that changed from the base of the PR and between 6f224a3 and 9a3351f.

📒 Files selected for processing (7)
  • pkg/mcs/scheduling/server/config/config.go
  • pkg/mcs/scheduling/server/config/config_test.go
  • pkg/schedule/config/config.go
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go
  • server/config/config_test.go
  • server/config/persist_options.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • pkg/mcs/scheduling/server/config/config.go
  • server/cluster/cluster_test.go
  • server/cluster/cluster.go
  • server/config/persist_options.go

@ti-chi-bot

ti-chi-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

@King-Dylan: Cannot trigger testing until a trusted user reviews the PR and leaves an /ok-to-test message.

Details

In response to this:

/ok-to-test

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.

@ti-chi-bot

ti-chi-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: bufferflies
Once this PR has been reviewed and has the lgtm label, please assign likidu 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 Aug 12, 2026
@ti-chi-bot

ti-chi-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

[LGTM Timeline notifier]

Timeline:

  • 2026-08-12 06:39:20.206457654 +0000 UTC m=+3201346.242552709: ☑️ agreed by bufferflies.

@bufferflies
bufferflies requested review from lhy1024 and rleungx August 12, 2026 06:39
…re-limit

Signed-off-by: King-Dylan <702299521@qq.com>

# Conflicts:
#	pkg/mcs/scheduling/server/config/config_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.

🧹 Nitpick comments (1)
pkg/mcs/scheduling/server/config/config_test.go (1)

123-123: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Use a distinct process default in the reload assertion.

The test persists RemovePeer as 15, then sets the process default to 15 before reading store 2. If default-store-limit.remove-peer is omitted or ignored during reload, the test still passes through the process default fallback. Set the process default to a different value after marshaling, while keeping the expected reloaded value at 15.

Proposed test adjustment
-	sc.DefaultStoreLimit.SetDefaultStoreLimit(storelimit.RemovePeer, 15)
+	sc.DefaultStoreLimit.SetDefaultStoreLimit(storelimit.RemovePeer, 25)

This validates the persisted-default-before-process-default precedence required by the PR objectives.

🤖 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/mcs/scheduling/server/config/config_test.go` at line 123, Update the
reload assertion setup around SetDefaultStoreLimit so the process-level
RemovePeer default is changed to a value different from the persisted 15 after
marshaling. Keep the expected reloaded store-2 value at 15, ensuring the
assertion verifies persisted configuration precedence over the process default.
🤖 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 `@pkg/mcs/scheduling/server/config/config_test.go`:
- Line 123: Update the reload assertion setup around SetDefaultStoreLimit so the
process-level RemovePeer default is changed to a value different from the
persisted 15 after marshaling. Keep the expected reloaded store-2 value at 15,
ensuring the assertion verifies persisted configuration precedence over the
process default.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 780b37df-7e20-4fab-b382-79195b103b50

📥 Commits

Reviewing files that changed from the base of the PR and between 9a3351f and 48ce41d.

📒 Files selected for processing (5)
  • pkg/mcs/scheduling/server/config/config.go
  • pkg/mcs/scheduling/server/config/config_test.go
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go
  • server/config/config_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • server/cluster/cluster_test.go
  • pkg/mcs/scheduling/server/config/config.go
  • server/config/config_test.go

AddPeer: sc.DefaultStoreLimit.GetDefaultStoreLimit(storelimit.AddPeer),
RemovePeer: sc.DefaultStoreLimit.GetDefaultStoreLimit(storelimit.RemovePeer),
}
limitCfg := cfg.GetDefaultStoreLimit()

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.

Config entries written by pre-upgrade PD do not contain default-store-limit; the MCS watcher unmarshals those entries into a zero-valued ScheduleConfig, so this fallback installs {0,0} for an unlisted store. In store-limit v1, zero is treated as unlimited, so a new store whose per-store entry has not been persisted can bypass add/remove-peer throttling after an upgrade.

@King-Dylan King-Dylan Aug 13, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 96d4b03. Persisted JSON now tracks default-store-limit field presence, and the MCS watcher initializes and migrates the watched schedule config before installing it. Legacy configs without the field now use the built-in default (or store-balance-rate when present), while explicit zero values remain unchanged. TestAdjustScheduleConfigDefaultStoreLimit covers these upgrade cases and the future-store lookup.

Comment thread pkg/schedule/config/config.go Outdated
defaultStoreLimit := StoreLimitConfig{AddPeer: c.StoreBalanceRate, RemovePeer: c.StoreBalanceRate}
DefaultStoreLimit = StoreLimit{AddPeer: defaultStoreLimit.AddPeer, RemovePeer: defaultStoreLimit.RemovePeer}
if defaultStoreLimitMeta == nil {
if c.DefaultStoreLimit == (StoreLimitConfig{}) {

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.

During reload of a legacy config that still contains store-balance-rate, Adjust(nil, true) has already filled DefaultStoreLimit with 15 before JSON unmarshalling, so this zero-value check never migrates the legacy rate. The deprecated field is then cleared and future stores silently fall back to 15 instead of the persisted rate.

@King-Dylan King-Dylan Aug 13, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 96d4b03. The persisted-config migration now uses per-field JSON presence instead of a zero-value sentinel, with precedence default-store-limit > store-balance-rate > process default. TestReloadLegacyStoreBalanceRate exercises the real Adjust -> JSON unmarshal -> migrate reload path and verifies that the legacy rate is retained for future stores.

Signed-off-by: King-Dylan <702299521@qq.com>
@King-Dylan
King-Dylan requested a review from rleungx August 13, 2026 04:42
Comment thread pkg/schedule/config/config.go
Signed-off-by: King-Dylan <702299521@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution This PR is from a community contributor. dco-signoff: yes Indicates the PR's author has signed the dco. needs-1-more-lgtm Indicates a PR needs 1 more LGTM. needs-ok-to-test Indicates a PR created by contributors and need ORG member send '/ok-to-test' to start testing. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Persist default store limit for future stores

3 participants