Skip to content

schedule, server: fix replicated state semantics - #11056

Open
rleungx wants to merge 10 commits into
tikv:masterfrom
rleungx:fix-regions-replicated-semantics
Open

schedule, server: fix replicated state semantics#11056
rleungx wants to merge 10 commits into
tikv:masterfrom
rleungx:fix-regions-replicated-semantics

Conversation

@rleungx

@rleungx rleungx commented Jul 28, 2026

Copy link
Copy Markdown
Member

What problem does this PR solve?

The /regions/replicated endpoint treats the RuleChecker pending list as the
final state. That list records a failed target selection and can become stale
after the Store topology changes, so schedulable work may still be reported as
PENDING. It can also report REPLICATED when Region metadata does not cover
the requested range.

Issue Number: Close #11055

What is changed and how does it work?

Evaluate current placement state for every scanned Region without creating
Operators or mutating RuleChecker caches or metrics.

Return PENDING only when the current topology has no legal action, INPROGRESS
for schedulable or retryable work, and REPLICATED once no work remains. Reuse
a shared orphan-peer planner so the query matches scheduling behavior.

Keep healthy Regions on the fit-only fast path. For incomplete Regions, reuse
the Store list within the range check and use existence-only candidate scans
that stop at the first legal target. Inspect the running and waiting operator
sets under read locks, and validate complete Region coverage.

Check List

Tests

  • Unit test
  • Integration test

Code changes

  • Has HTTP API behavior changed

Side effects

  • Healthy Regions stay on the fit-only fast path. For incomplete Regions,
    reuse the Store list within the range check and stop candidate scans at the
    first legal target.
  • Operator inspection only takes read locks and does not maintain a per-Region
    waiting-operator index.

Release note

Fix inaccurate placement scheduling states returned by the regions replicated API.

Summary by CodeRabbit

  • New Features

    • Replication status checks now more precisely distinguish PENDING (blocked by unavailable placement/peers) from INPROGRESS (work can continue or retry), including gaps or incomplete region metadata.
    • Placement-rule-aware evaluation better reflects orphan peer handling, alternative-leader availability, and isolation/peer state constraints.
  • Bug Fixes

    • Improved correctness of replicated vs progress states for ranges affected by missing data, scanned gaps, offline/down peers, and leader-rejection scenarios.
    • Updated API documentation for /regions/replicated to match the refined status meanings.
  • Tests

    • Expanded coverage for the new status transitions and edge cases.

@ti-chi-bot ti-chi-bot Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. do-not-merge/needs-triage-completed dco-signoff: yes Indicates the PR's author has signed the dco. labels Jul 28, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 28, 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 bufferflies 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 size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Jul 28, 2026
@coderabbitai

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

Placement state reporting

Layer / File(s) Summary
Operator detection
pkg/schedule/operator/*
Indexes waiting operators by region and exposes replica-kind detection across running and queued operators.
Placement state evaluation
pkg/schedule/checker/rule_checker.go, pkg/schedule/checker/replica_strategy.go, pkg/schedule/checker/checker_controller.go
Classifies placement as replicated, in progress, or pending using peer roles, orphan actions, store availability, isolation, cached candidates, and stale pending-region handling.
Replicated-region API status flow
pkg/schedule/handler/handler.go, pkg/mcs/scheduling/server/apis/v1/api.go, server/api/region.go
Validates contiguous range coverage and maps placement state, replica operators, and incomplete replication to REPLICATED, PENDING, or INPROGRESS.
Replicated-region status validation
pkg/schedule/checker/rule_checker_test.go, tests/server/api/region_test.go
Tests placement transitions, store-loading behavior, unavailable targets, isolation constraints, and incomplete or discontinuous Region metadata.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant CheckRegionsReplicated
  participant RuleChecker
  participant ReplicaStrategy
  Client->>CheckRegionsReplicated: Request replicated status
  CheckRegionsReplicated->>CheckRegionsReplicated: Validate range coverage
  CheckRegionsReplicated->>RuleChecker: Evaluate placement state
  RuleChecker->>ReplicaStrategy: Find eligible placement candidates
  ReplicaStrategy-->>RuleChecker: Candidate stores
  RuleChecker-->>CheckRegionsReplicated: Placement state
  CheckRegionsReplicated-->>Client: Return API status
Loading

Possibly related issues

  • tikv/pd issue 10149 — Both changes address placement-state validation involving region label isolation.

Suggested labels: lgtm, approved

Suggested reviewers: lhy1024, jmpotato

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% 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 The changes satisfy #11055 by distinguishing REPLICATED, INPROGRESS, and PENDING according to current topology and incomplete range metadata.
Out of Scope Changes check ✅ Passed The additional checker and operator changes support the replicated-state fix and do not appear unrelated to the requested behavior.
Title check ✅ Passed The title clearly summarizes the main change to replicated-state semantics across schedule and server code.
Description check ✅ Passed The description includes the required issue number, change summary, checklist, and release note sections.
✨ 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.

🧹 Nitpick comments (7)
pkg/schedule/checker/rule_checker_state.go (1)

152-155: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the context parameter.

context shadows the stdlib package name and reads like a context.Context, which it isn't. The sibling methods already use ctx *regionPlacementStateContext; something like stateCtx (or matching ctx) keeps it consistent and unambiguous.

🤖 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/checker/rule_checker_state.go` around lines 152 - 155, Rename
the context parameter in RuleChecker.evaluateRegionPlacementState from context
to ctx or stateCtx, and update all references within the method body to match.
Keep its type and behavior unchanged, aligning with the sibling methods’ naming
convention.
server/api/region.go (1)

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

Regenerate the Swagger spec after changing these annotations. Both endpoints' @Summary text changed, so the committed spec is now stale.

  • server/api/region.go#L139-L139: run make swagger-spec (SWAGGER=1) and commit the regenerated output for this summary change.
  • pkg/mcs/scheduling/server/apis/v1/api.go#L1469-L1469: ensure the scheduling microservice spec is regenerated with the same wording.

As per coding guidelines: "Regenerate Swagger spec with make swagger-spec (SWAGGER=1) when API annotations change".

🤖 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/api/region.go` at line 139, Regenerate and commit the Swagger
specifications after the summary annotation changes: run make swagger-spec with
SWAGGER=1 for server/api/region.go:139-139 and update the generated output,
ensuring pkg/mcs/scheduling/server/apis/v1/api.go:1469-1469 reflects the same
wording; no direct source change is required beyond the annotation updates.

Source: Coding guidelines

pkg/schedule/checker/rule_checker_state_test.go (1)

445-451: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Cryptic zone labels in the benchmark.

string(rune(i)) yields control characters and makes the intentional collision between store 1 and store 1001 hard to see. fmt.Sprintf("z%d", i) (with "z1" for 1001) would express the intent directly.

🤖 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/checker/rule_checker_state_test.go` around lines 445 - 451,
Update the benchmark setup around AddLabelsStore to use readable zone labels
formatted as “z” plus the store ID, and assign store 1001 the intentional
colliding label “z1” instead of converting IDs to runes. Preserve the existing
store and leader-region relationships.
pkg/schedule/placement/fit.go (1)

152-166: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Exported method can panic on nil Stores entries.

Stores may contain nil (e.g. cloneRegionFitWithStores in rule_manager.go fills via getStoreByID, which can miss). The current RuleChecker caller pre-validates non-nil stores, but this is an exported method; a cheap guard makes it robust.

🛡️ Proposed guard
 	highestLevel := f.Rule.LocationLabels[0]
 	for i, store := range f.Stores {
+		if store == nil {
+			continue
+		}
 		labelValue := store.GetLabelValue(highestLevel)
 		for _, other := range f.Stores[i+1:] {
-			if labelValue == other.GetLabelValue(highestLevel) {
+			if other != nil && labelValue == other.GetLabelValue(highestLevel) {
 				return false
 			}
 		}
 	}
🤖 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/placement/fit.go` around lines 152 - 166, Update
RuleFit.IsolatedAtHighestLevel to safely handle nil entries in f.Stores before
calling GetLabelValue; return a non-panicking result consistent with invalid or
incomplete store data, while preserving the existing label and peer-count
behavior for valid stores.
pkg/schedule/placement/rule_manager_test.go (1)

511-518: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assertion can pass vacuously.

If no RuleFit peer matches refreshedStore, the loop body never executes and the test still passes. Track a flag and require it.

♻️ Proposed tightening
 	readFit = manager.FitRegionForRead(stores, region)
+	checked := false
 	for _, ruleFit := range readFit.RuleFits {
 		for i, peer := range ruleFit.Peers {
 			if peer.GetStoreId() == refreshedStore.GetID() {
 				re.Same(refreshedStore, ruleFit.Stores[i])
+				checked = true
 			}
 		}
 	}
+	re.True(checked)
🤖 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/placement/rule_manager_test.go` around lines 511 - 518, Update
the assertions in the FitRegionForRead test around readFit.RuleFits to track
whether any peer matches refreshedStore.GetID(), require that a match was found
after the loops, and retain the existing re.Same assertion for the corresponding
ruleFit.Stores entry.
pkg/schedule/checker/replica_strategy.go (1)

240-281: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

selectStoreToRemoveForState duplicates selectStoreToRemoveWithTempState semantics.

Two independent implementations of "which store would be removed" will drift; the parity test only pins two scenarios. Consider extracting the shared selection into one helper used by both the operator path and the read-only state path (e.g. a function returning permissive/strict candidates that the existing method wraps).

🤖 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/checker/replica_strategy.go` around lines 240 - 281, Unify the
duplicate store-selection logic used by selectStoreToRemoveForState and
selectStoreToRemoveWithTempState by extracting their shared permissive/strict
candidate selection into one helper. Update both callers to use that helper
while preserving each method’s existing return behavior and filtering semantics.
pkg/schedule/handler/handler.go (1)

1316-1335: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a GoDoc comment for the range-coverage contract.

The empty-end-key semantics (unbounded range requires an unbounded last region) are subtle enough to deserve a one-line comment above the helper.

🤖 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/handler/handler.go` around lines 1316 - 1335, Add a concise
GoDoc comment immediately above regionsCoverRange documenting its range-coverage
contract, including that an empty endKey denotes an unbounded range and
therefore requires the final region to have an empty end key.
🤖 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/schedule/checker/replica_strategy.go`:
- Around line 240-281: Unify the duplicate store-selection logic used by
selectStoreToRemoveForState and selectStoreToRemoveWithTempState by extracting
their shared permissive/strict candidate selection into one helper. Update both
callers to use that helper while preserving each method’s existing return
behavior and filtering semantics.

In `@pkg/schedule/checker/rule_checker_state_test.go`:
- Around line 445-451: Update the benchmark setup around AddLabelsStore to use
readable zone labels formatted as “z” plus the store ID, and assign store 1001
the intentional colliding label “z1” instead of converting IDs to runes.
Preserve the existing store and leader-region relationships.

In `@pkg/schedule/checker/rule_checker_state.go`:
- Around line 152-155: Rename the context parameter in
RuleChecker.evaluateRegionPlacementState from context to ctx or stateCtx, and
update all references within the method body to match. Keep its type and
behavior unchanged, aligning with the sibling methods’ naming convention.

In `@pkg/schedule/handler/handler.go`:
- Around line 1316-1335: Add a concise GoDoc comment immediately above
regionsCoverRange documenting its range-coverage contract, including that an
empty endKey denotes an unbounded range and therefore requires the final region
to have an empty end key.

In `@pkg/schedule/placement/fit.go`:
- Around line 152-166: Update RuleFit.IsolatedAtHighestLevel to safely handle
nil entries in f.Stores before calling GetLabelValue; return a non-panicking
result consistent with invalid or incomplete store data, while preserving the
existing label and peer-count behavior for valid stores.

In `@pkg/schedule/placement/rule_manager_test.go`:
- Around line 511-518: Update the assertions in the FitRegionForRead test around
readFit.RuleFits to track whether any peer matches refreshedStore.GetID(),
require that a match was found after the loops, and retain the existing re.Same
assertion for the corresponding ruleFit.Stores entry.

In `@server/api/region.go`:
- Line 139: Regenerate and commit the Swagger specifications after the summary
annotation changes: run make swagger-spec with SWAGGER=1 for
server/api/region.go:139-139 and update the generated output, ensuring
pkg/mcs/scheduling/server/apis/v1/api.go:1469-1469 reflects the same wording; no
direct source change is required beyond the annotation updates.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ad920e4c-eed3-4e1b-bbe4-6a2191ce00e9

📥 Commits

Reviewing files that changed from the base of the PR and between 070828c and 5dca009.

📒 Files selected for processing (12)
  • pkg/mcs/scheduling/server/apis/v1/api.go
  • pkg/schedule/checker/replica_strategy.go
  • pkg/schedule/checker/rule_checker_state.go
  • pkg/schedule/checker/rule_checker_state_test.go
  • pkg/schedule/handler/handler.go
  • pkg/schedule/handler/handler_test.go
  • pkg/schedule/placement/fit.go
  • pkg/schedule/placement/fit_test.go
  • pkg/schedule/placement/rule_manager.go
  • pkg/schedule/placement/rule_manager_test.go
  • server/api/region.go
  • tests/server/api/region_test.go

@rleungx

rleungx commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

/retest

Treat the RuleChecker pending list as a hint and revalidate missing placement-rule peers against the current Store topology. Report PENDING only when no add or swap target exists; otherwise report INPROGRESS. Also avoid reporting uncovered Region ranges as replicated.

Signed-off-by: Ryan Leung <rleungx@gmail.com>
@rleungx
rleungx force-pushed the fix-regions-replicated-semantics branch from 5dca009 to 9a4df95 Compare July 28, 2026 07:20
@rleungx rleungx changed the title schedule, server: report placement scheduling state schedule, server: fix replicated state semantics Jul 28, 2026
@ti-chi-bot ti-chi-bot Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jul 28, 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/handler/handler.go`:
- Around line 1304-1318: The topology-based PENDING classification in
pkg/schedule/handler/handler.go lines 1304-1318 must evaluate
GetRuleChecker().GetRegionPlacementState(region) independently of
co.IsPendingRegion; retain completed-Region scan avoidance through a separate
fast path. Add a test in tests/server/api/region_test.go lines 211-240 with
mockPending false or disabled and a no-legal-target offline peer, asserting the
region is reported as PENDING.
🪄 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 Plus

Run ID: 341f8b5f-36f6-461d-a653-a8198a71ac6e

📥 Commits

Reviewing files that changed from the base of the PR and between 5dca009 and 9a4df95.

📒 Files selected for processing (6)
  • pkg/mcs/scheduling/server/apis/v1/api.go
  • pkg/schedule/checker/rule_checker.go
  • pkg/schedule/checker/rule_checker_test.go
  • pkg/schedule/handler/handler.go
  • server/api/region.go
  • tests/server/api/region_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • server/api/region.go
  • pkg/mcs/scheduling/server/apis/v1/api.go

Comment thread pkg/schedule/handler/handler.go Outdated
@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.39796% with 69 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.32%. Comparing base (070828c) to head (8e9a02f).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #11056      +/-   ##
==========================================
+ Coverage   79.23%   79.32%   +0.08%     
==========================================
  Files         540      541       +1     
  Lines       76010    76635     +625     
==========================================
+ Hits        60226    60788     +562     
- Misses      11533    11569      +36     
- Partials     4251     4278      +27     
Flag Coverage Δ
unittests 79.32% <82.39%> (+0.08%) ⬆️

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

@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/handler/handler.go (1)

1305-1319: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Pending classification is still gated by RuleChecker's internal pending-list cache.

Regions where co.IsPendingRegion returns false bypass GetRegionsPlacementState entirely and fall back to the old filter.IsRegionReplicated check, which cannot report PENDING. So a Region with a genuinely unfixable placement problem that RuleChecker's patrol hasn't yet flagged as pending will be reported INPROGRESS instead of PENDING, contradicting the objective that PENDING should be based on the current topology, not on RuleChecker's cache membership.

This mirrors the concern raised on an earlier commit of this PR: evaluate placement feasibility from the current topology independently of co.IsPendingRegion, and use the pending-list only as an optimization to skip already-known-fine Regions (e.g., short-circuit only after filter.IsRegionReplicated/rule-fit succeeds).

🤖 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/handler/handler.go` around lines 1305 - 1319, Update the
placement-state logic around co.IsPendingRegion so PENDING classification is
determined from current topology feasibility rather than requiring cached
pending membership. Use co.IsPendingRegion only as an optimization for
already-known-fine regions, while ensuring regions that fail
filter.IsRegionReplicated or the relevant rule-fit check are evaluated and
reported as PENDING when unfixable; preserve the existing INPROGRESS behavior
for regions with recoverable placement work.
🤖 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/handler/handler.go`:
- Around line 1305-1319: Update the placement-state logic around
co.IsPendingRegion so PENDING classification is determined from current topology
feasibility rather than requiring cached pending membership. Use
co.IsPendingRegion only as an optimization for already-known-fine regions, while
ensuring regions that fail filter.IsRegionReplicated or the relevant rule-fit
check are evaluated and reported as PENDING when unfixable; preserve the
existing INPROGRESS behavior for regions with recoverable placement work.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 28e0f013-6f89-4062-a4b8-86e33dde6992

📥 Commits

Reviewing files that changed from the base of the PR and between 9a4df95 and 703ccc1.

📒 Files selected for processing (5)
  • pkg/schedule/checker/checker_controller.go
  • pkg/schedule/checker/replica_strategy.go
  • pkg/schedule/checker/rule_checker.go
  • pkg/schedule/checker/rule_checker_test.go
  • pkg/schedule/handler/handler.go

rleungx added 3 commits July 28, 2026 17:46
Evaluate placement states without relying on the RuleChecker pending LRU, distinguish retryable work from unschedulable topology, and keep completed-range checks on the fast path. Reuse Store candidates across incomplete Regions and cover active replica operators and missing Region metadata.

Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
Signed-off-by: Ryan Leung <rleungx@gmail.com>
@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 Jul 30, 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 (4)
pkg/schedule/operator/waiting_operator.go (1)

162-178: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Nil the vacated slot before truncating.

The swap-remove leaves the removed operator referenced by the backing array past len(ops), keeping it (and its region snapshot) alive. The bucket code in GetOperator explicitly nils entries for this reason.

♻️ Proposed change
 		ops[i] = ops[len(ops)-1]
+		ops[len(ops)-1] = nil // avoid memory leak
 		ops = ops[:len(ops)-1]
 		break
🤖 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/operator/waiting_operator.go` around lines 162 - 178, Update
randBuckets.removeOperatorFromRegion to clear the vacated final slot in ops
before truncating the slice, matching the cleanup behavior used by GetOperator.
Preserve the existing swap-remove logic and region-map deletion behavior.
pkg/schedule/checker/checker_controller.go (1)

269-274: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Also drop the pending entry for vanished Regions.

A merged/removed Region keeps its ID in pendingProcessedRegions until TTL expiry, and evaluateRegionPlacementState treats membership as InProgress. Removing it here matches the new "remove before check" policy.

♻️ Proposed change
 		if region == nil {
+			c.RemovePendingProcessedRegion(id)
 			continue
 		}
🤖 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/checker/checker_controller.go` around lines 269 - 274, Update
the region iteration in the checker controller so a nil or vanished region also
removes its ID from pendingProcessedRegions before continuing. Apply
RemovePendingProcessedRegion(id) before the region == nil branch, while
preserving the existing removal-before-check behavior for non-nil regions.
tests/server/api/region_test.go (1)

219-240: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer testutil.Eventually for these status assertions, and document the restore block.

Every other /regions/replicated assertion in this test polls; these two read once right after mutating store state through PutStore on both the PD and scheduling clusters, which is more exposed to propagation timing in the scheduling-server variant. Lines 236-240 also silently reset store 1 to serving and store 2 to offline so the later PENDING expectation holds — worth a one-line comment.

🤖 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/server/api/region_test.go` around lines 219 - 240, Update the two
status checks around the mutations to targetStore and availableTarget in the
replicated-region test to use testutil.Eventually, polling until the expected
PENDING and INPROGRESS values are observed. Add a concise comment before the
final putStore calls explaining that they restore store 1 to serving and store 2
to offline for the subsequent PENDING assertion.
pkg/schedule/checker/rule_checker.go (1)

317-421: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

hasOrphanPeerAction duplicates fixOrphanPeers policy; consider a shared decision helper.

This re-implements the orphan-handling decision tree (first-orphan preference, pin-down replacement, joint-consensus role rules, extra-count heuristics) that fixOrphanPeers encodes. Any future change to one side silently desynchronizes the reported placement state from what the checker actually does. Extracting a common "which orphan action applies" step that both the operator path and the state path consume would keep them in lockstep.

🤖 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/checker/rule_checker.go` around lines 317 - 421, The
orphan-handling policy is duplicated between hasOrphanPeerAction and
fixOrphanPeers, risking inconsistent checker results and operator behavior.
Extract a shared decision helper that determines the applicable orphan action,
including first-orphan selection, pin-down replacement, role handling,
joint-consensus checks, and extra-count heuristics; update both
hasOrphanPeerAction and fixOrphanPeers to consume that helper while preserving
their existing outcomes.
🤖 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/schedule/checker/checker_controller.go`:
- Around line 269-274: Update the region iteration in the checker controller so
a nil or vanished region also removes its ID from pendingProcessedRegions before
continuing. Apply RemovePendingProcessedRegion(id) before the region == nil
branch, while preserving the existing removal-before-check behavior for non-nil
regions.

In `@pkg/schedule/checker/rule_checker.go`:
- Around line 317-421: The orphan-handling policy is duplicated between
hasOrphanPeerAction and fixOrphanPeers, risking inconsistent checker results and
operator behavior. Extract a shared decision helper that determines the
applicable orphan action, including first-orphan selection, pin-down
replacement, role handling, joint-consensus checks, and extra-count heuristics;
update both hasOrphanPeerAction and fixOrphanPeers to consume that helper while
preserving their existing outcomes.

In `@pkg/schedule/operator/waiting_operator.go`:
- Around line 162-178: Update randBuckets.removeOperatorFromRegion to clear the
vacated final slot in ops before truncating the slice, matching the cleanup
behavior used by GetOperator. Preserve the existing swap-remove logic and
region-map deletion behavior.

In `@tests/server/api/region_test.go`:
- Around line 219-240: Update the two status checks around the mutations to
targetStore and availableTarget in the replicated-region test to use
testutil.Eventually, polling until the expected PENDING and INPROGRESS values
are observed. Add a concise comment before the final putStore calls explaining
that they restore store 1 to serving and store 2 to offline for the subsequent
PENDING assertion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 90aec105-7972-48c4-ada0-50c2f55eaaed

📥 Commits

Reviewing files that changed from the base of the PR and between c419ffb and d4cd707.

📒 Files selected for processing (8)
  • pkg/schedule/checker/checker_controller.go
  • pkg/schedule/checker/rule_checker.go
  • pkg/schedule/checker/rule_checker_test.go
  • pkg/schedule/handler/handler.go
  • pkg/schedule/operator/operator_controller.go
  • pkg/schedule/operator/waiting_operator.go
  • pkg/schedule/operator/waiting_operator_test.go
  • tests/server/api/region_test.go

rleungx added 5 commits July 30, 2026 14:07
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>
@ti-chi-bot

ti-chi-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

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

Test name Commit Details Required Rerun command
pull-unit-test-next-gen-3 8e9a02f 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. release-note Denotes a PR that will be considered when it comes time to generate release notes. 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.

/regions/replicated reports incorrect placement scheduling state

1 participant