Skip to content

pkg/ddl, pkg/tici: add TiCI pre-split for DDL global sort ingest | tidb-test=13ccf8de48e8db2290ff884598444d0508606bbf tiflash=feature-fts - #67124

Merged
ti-chi-bot[bot] merged 14 commits into
pingcap:feature/ftsfrom
3pointer:presplit_tici
Mar 26, 2026

Conversation

@3pointer

@3pointer 3pointer commented Mar 18, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #xxx

Problem Summary:

When TiDB builds FULLTEXT or HYBRID indexes with the TiCI backend in global sort mode, TiCI does not get an early pre-split signal before the write-and-ingest stage starts. As a result, TiCI cannot use the aggregated SortedKV metadata to analyze shard distribution and split internal shards ahead of ingest.

In addition, the TiDB side does not define the corresponding PreSplitImportShards RPC yet, so the pre-split request cannot be sent with the required metadata.

What changed and how does it work?

This PR is scoped to DDL backfill only (ADD FULLTEXT INDEX / ADD HYBRID INDEX). IMPORT INTO is not supported in this PR; follow-up changes can be made separately if needed.

This PR adds a TiCI pre-split hook in generateGlobalSortIngestPlan for TiCI-backed FULLTEXT and HYBRID index jobs.

The main changes are:

  • Add PreSplitImportShards RPC and related request/response messages to pkg/tici/tici.proto, then regenerate pkg/tici/tici.pb.go.
  • Add TiCI client support in pkg/tici/tici_manager_client.go to call PreSplitImportShards, including keyspace propagation and test failpoint hooks.
  • In generateGlobalSortIngestPlan, detect ActionAddFullTextIndex and ActionAddHybridIndex, aggregate merged SortedKVMeta groups, and build a TiCI pre-split request with:
    • global start_key / end_key
    • total_kv_size / total_kv_cnt
    • data_file_count / stat_file_count
    • per-group metadata in meta_groups
  • Call the TiCI pre-split RPC synchronously with a 1 minute timeout before generating the final ingest plan.
  • If the TiCI pre-split call fails, log the error and degrade to the existing global-sort ingest flow instead of failing the whole DDL job.
  • Add a guard in FULLTEXT index creation to require cloud storage, because TiCI pre-split only applies to the global-sort ingest path.
  • Add unit tests for both the DDL scheduler flow and the TiCI client request path.

Check List

Tests

  • Unit test

    Suggested / used test commands:

    • make failpoint-enable && (cd pkg/ddl && go test -run TestBackfillingSchedulerGlobalSortModeTiCIPreSplit --tags=intest; rc=$?; cd ../..; make failpoint-disable; exit $rc)
    • go test -run TestPreSplitImportShards --tags=intest ./pkg/tici
    • go test -run TestPreSplitImportShardsMock --tags=intest ./pkg/tici
  • 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

Support calling TiCI PreSplitImportShards before global-sort ingest for FULLTEXT and HYBRID index backfill jobs.


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * TiCI pre-split support added to coordinate shard pre-splitting before importing full-text/hybrid index backfills; pre-split RPC and orchestration included.
  * Range-splitting now tracks exact per-group size/key counts to improve import grouping accuracy.

* **Tests**
  * Added unit and integration tests validating TiCI pre-split requests, request contents, unique file counting, and range-split behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

@ti-chi-bot

ti-chi-bot Bot commented Mar 18, 2026

Copy link
Copy Markdown

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

@ti-chi-bot ti-chi-bot Bot added do-not-merge/invalid-title do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. release-note-none Denotes a PR that doesn't merit a release note. labels Mar 18, 2026
@coderabbitai

coderabbitai Bot commented Mar 18, 2026 •

Copy link
Copy Markdown

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

Adds TiCI pre-split orchestration to distributed/global-sort DDL backfilling for full-text/hybrid indexes, extends range-splitting to return group size/key count, introduces a TiCI PreSplitImportShards RPC and client support, and adds tests and failpoints to validate pre-split behavior.

Changes

Cohort / File(s) Summary
DDL Scheduler & TiCI Orchestration
pkg/ddl/backfilling_dist_scheduler.go
Add storageWithPDAndCodec type-check, pass codec-enabled store into global-sort ingest plan, call TiCI PreSplitImportShards (1 min timeout) for full-text/hybrid index actions, build report groups, add failpoint hook and continue planning on TiCI errors.
DDL Scheduler Tests
pkg/ddl/backfilling_dist_scheduler_test.go, pkg/ddl/backfilling_dist_scheduler_internal_test.go
Add end-to-end and unit tests for TiCI pre-split: write SortedKVMeta via DXF, enable TiCI failpoint, assert generated PreSplitImportShards request contents and unique file counting; test storage helper type-check behavior.
Range Splitter Signature & Callsites
pkg/lightning/backend/external/split.go, pkg/lightning/backend/external/split_test.go, pkg/lightning/backend/external/testutil.go, pkg/dxf/importinto/planner.go, pkg/lightning/backend/external/merge_v2.go
Extend SplitOneRangesGroup() to return groupSize uint64 and groupKeyCnt uint64; update call sites/tests to accept or ignore new returns and add assertions validating group metrics.
DXF / Planner Adjustments
pkg/dxf/importinto/planner.go
Ignore additional return values from updated SplitOneRangesGroup() while preserving existing control flow and error handling.
TiCI Proto, Client & Tests
pkg/tici/tici.proto, pkg/tici/tici_manager_client.go, pkg/tici/tici_manager_client_test.go
Add PreSplitImportShards RPC and messages, implement client methods (manager method + top-level helper) with keyspace derivation, add failpoint-based mock capture/reset, and unit tests for success/error/serialization paths.
TiCI Build Config
pkg/tici/BUILD.bazel
Add dependency on @com_github_tikv_client_go_v2//tikv, add failpoint dep to tici_test, and increase tici_test shard_count from 24 to 26.

Sequence Diagram

sequenceDiagram
    participant Scheduler as DDL Scheduler
    participant Splitter as RangeSplitter
    participant TiCI as TiCI Service
    participant Store as KV Storage

    Scheduler->>Splitter: SplitOneRangesGroup()
    Splitter-->>Scheduler: (endKey, dataFiles, statFiles, groupSize, groupKeyCnt, ...)
    Scheduler->>Scheduler: Aggregate groups -> Build PreSplitImportShardsRequest
    Scheduler->>TiCI: PreSplitImportShards(request) (1 min timeout)
    TiCI-->>Scheduler: PreSplitImportShardsResponse (success / error)
    alt Success
        Scheduler->>Scheduler: Incorporate TiCI split info into plan
    else Failure
        Scheduler->>Scheduler: Log error, continue with default plan
    end
    Scheduler->>Store: Execute global-sort ingest plan
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

ok-to-test

Suggested reviewers

  • wjhuang2016
  • D3Hunter
  • joechenrh
  • mjonss

Poem

🐰 I counted files, split the range with care,

Sent tiny reports to TiCI in the air,
Failpoints set, requests all tidy and neat,
Shards found their places—no duplicate beat,
Hooray for sorted bytes and planner’s fleet!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically identifies the main change: adding TiCI pre-split functionality for DDL global sort ingest in the pkg/ddl and pkg/tici packages.
Description check ✅ Passed The PR description covers problem statement, solution approach, implementation details, test coverage, and release notes, closely following the template structure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

@ti-chi-bot ti-chi-bot Bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Mar 18, 2026
@tiprow

tiprow Bot commented Mar 18, 2026

Copy link
Copy Markdown

Hi @3pointer. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

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.

@3pointer 3pointer changed the title Presplit tici pkg/ddl, pkg/tici: add TiCI pre-split for global sort ingest Mar 18, 2026
@3pointer

Copy link
Copy Markdown
Contributor Author

/build

@3pointer
3pointer marked this pull request as ready for review March 23, 2026 08:18
@ti-chi-bot ti-chi-bot Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 23, 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: 2

🧹 Nitpick comments (1)
pkg/ddl/backfilling_dist_scheduler.go (1)

178-186: Avoid an unchecked storageWithPDAndCodec cast here.

getUserStoreAndTable() still returns kv.Storage, so this assertion turns any wrapper/mock without GetCodec() into a scheduler panic instead of a normal DDL error. Returning an error keeps retries and fallback logic in-band.

Possible fix
-			return generateGlobalSortIngestPlan(
-				ctx,
-				store.(storageWithPDAndCodec),
-				taskHandle,
-				task,
-				&backfillMeta,
-				backfillMeta.CloudStorageURI,
-				backfillMeta.ScanSnapshotTS,
-				logger)
+			codecStore, ok := store.(storageWithPDAndCodec)
+			if !ok {
+				return nil, errors.Errorf("storage %T does not expose codec", store)
+			}
+			return generateGlobalSortIngestPlan(
+				ctx,
+				codecStore,
+				taskHandle,
+				task,
+				&backfillMeta,
+				backfillMeta.CloudStorageURI,
+				backfillMeta.ScanSnapshotTS,
+				logger)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/ddl/backfilling_dist_scheduler.go` around lines 178 - 186, The code
currently does an unchecked type assertion to storageWithPDAndCodec when calling
generateGlobalSortIngestPlan, which can panic if getUserStoreAndTable returned a
kv.Storage wrapper/mock without GetCodec; change this to a safe type check: test
whether store is a storageWithPDAndCodec (using a typed assertion with ok) and
if not return a proper error from the calling function so the scheduler handles
it as a DDL error and keeps retry/fallback logic in-band; update the call site
that currently passes store.(storageWithPDAndCodec) into
generateGlobalSortIngestPlan to use the validated typed value or return the new
error, and ensure error messages reference
getUserStoreAndTable/storageWithPDAndCodec to aid debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/ddl/backfilling_dist_scheduler.go`:
- Around line 530-536: The failpoint Inject named
"mockGenerateGlobalSortIngestPlanAfterPreSplit" currently returns before the
pre-split logic so triggerTiCIPreSplitImportShards() never runs; either relocate
the failpoint.Inject block so it is executed after the pre-split section (so
triggerTiCIPreSplitImportShards() runs during tests) or rename the failpoint to
accurately reflect that it short-circuits before pre-split; update the instance
in backfilling_dist_scheduler.go (the failpoint.Inject call and the mock name)
and any tests that enable this failpoint to match the chosen fix.

In `@pkg/ddl/index.go`:
- Around line 1611-1618: The current cloudStorageURI validation runs too early
and can break retries/owner handoffs; move the check into the FULLTEXT job
initialization branch by calling loadCloudStorageURI(job) during model.StateNone
handling and then validating job.ReorgMeta.UseCloudStorage instead of directly
using handle.GetCloudStorageURI(w.workCtx, w.store); specifically, update the
initialization path that handles model.StateNone to call
loadCloudStorageURI(job) and return dbterror.ErrUnsupportedAddColumnarIndex if
job.ReorgMeta.UseCloudStorage is false so subsequent states rely on the fixed
value in job.ReorgMeta rather than a global GetCloudStorageURI call.

---

Nitpick comments:
In `@pkg/ddl/backfilling_dist_scheduler.go`:
- Around line 178-186: The code currently does an unchecked type assertion to
storageWithPDAndCodec when calling generateGlobalSortIngestPlan, which can panic
if getUserStoreAndTable returned a kv.Storage wrapper/mock without GetCodec;
change this to a safe type check: test whether store is a storageWithPDAndCodec
(using a typed assertion with ok) and if not return a proper error from the
calling function so the scheduler handles it as a DDL error and keeps
retry/fallback logic in-band; update the call site that currently passes
store.(storageWithPDAndCodec) into generateGlobalSortIngestPlan to use the
validated typed value or return the new error, and ensure error messages
reference getUserStoreAndTable/storageWithPDAndCodec to aid debugging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 511225db-7053-4211-b42b-f69d16c4588a

📥 Commits

Reviewing files that changed from the base of the PR and between 3ff0fa4 and d29239a.

⛔ Files ignored due to path filters (1)
  • pkg/tici/tici.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (11)
  • pkg/ddl/backfilling_dist_scheduler.go
  • pkg/ddl/backfilling_dist_scheduler_test.go
  • pkg/ddl/index.go
  • pkg/dxf/importinto/planner.go
  • pkg/lightning/backend/external/merge_v2.go
  • pkg/lightning/backend/external/split.go
  • pkg/lightning/backend/external/split_test.go
  • pkg/lightning/backend/external/testutil.go
  • pkg/tici/tici.proto
  • pkg/tici/tici_manager_client.go
  • pkg/tici/tici_manager_client_test.go

Comment thread pkg/ddl/backfilling_dist_scheduler.go
Comment thread pkg/ddl/index.go Outdated
Comment on lines +1611 to +1618
cloudStorageURI := handle.GetCloudStorageURI(w.workCtx, w.store)
// DXF pre-split index requires cloud storage.
// local ingest doesn't keep a global order and pre-split is not supported.
// FullText index already communiate with tici a cloud storage uri.
// TODO: Another fallback is to use the cloud storage uri from tici if not set.
if len(cloudStorageURI) == 0 {
return ver, errors.Trace(dbterror.ErrUnsupportedAddColumnarIndex.FastGen("FULLTEXT index requires cloud storage"))
}

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

Validate cloud storage only when the FULLTEXT job is initialized.

Because this runs before the indexInfo.State switch, a FULLTEXT job that already passed StateNone can start failing on retry / owner handoff if the global cloud-storage URI is changed or cleared mid-DDL. The chosen URI should be fixed once during setup and reused from job/task state afterward.

Possible fix
-	cloudStorageURI := handle.GetCloudStorageURI(w.workCtx, w.store)
-	// DXF pre-split index requires cloud storage.
-	// local ingest doesn't keep a global order and pre-split is not supported.
-	// FullText index already communiate with tici a cloud storage uri.
-	// TODO: Another fallback is to use the cloud storage uri from tici if not set.
-	if len(cloudStorageURI) == 0 {
-		return ver, errors.Trace(dbterror.ErrUnsupportedAddColumnarIndex.FastGen("FULLTEXT index requires cloud storage"))
-	}
case model.StateNone:
	loadCloudStorageURI(w, job)
	if !job.ReorgMeta.UseCloudStorage {
		return ver, errors.Trace(dbterror.ErrUnsupportedAddColumnarIndex.FastGen("FULLTEXT index requires cloud storage"))
	}
	// continue initialization...
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/ddl/index.go` around lines 1611 - 1618, The current cloudStorageURI
validation runs too early and can break retries/owner handoffs; move the check
into the FULLTEXT job initialization branch by calling loadCloudStorageURI(job)
during model.StateNone handling and then validating
job.ReorgMeta.UseCloudStorage instead of directly using
handle.GetCloudStorageURI(w.workCtx, w.store); specifically, update the
initialization path that handles model.StateNone to call
loadCloudStorageURI(job) and return dbterror.ErrUnsupportedAddColumnarIndex if
job.ReorgMeta.UseCloudStorage is false so subsequent states rely on the fixed
value in job.ReorgMeta rather than a global GetCloudStorageURI call.

@codecov

codecov Bot commented Mar 23, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 67.04871% with 115 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.7511%. Comparing base (bd3b320) to head (d5434fb).
⚠️ Report is 25 commits behind head on feature/fts.

Additional details and impacted files
@@                 Coverage Diff                 @@
##           feature/fts     #67124        +/-   ##
===================================================
- Coverage      76.8610%   76.7511%   -0.1099%     
===================================================
  Files             1960       1962         +2     
  Lines           555677     558695      +3018     
===================================================
+ Hits            427099     428805      +1706     
- Misses          127116     128424      +1308     
- Partials          1462       1466         +4     
Flag Coverage Δ
integration 45.3456% <0.0000%> (-0.2638%) ⬇️
unit 73.9592% <67.0487%> (-0.0890%) ⬇️

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

Components Coverage Δ
dumpling 56.7974% <ø> (+0.0929%) ⬆️
parser ∅ <ø> (∅)
br 66.2603% <ø> (+0.0156%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@3pointer 3pointer changed the title pkg/ddl, pkg/tici: add TiCI pre-split for global sort ingest pkg/ddl, pkg/tici: add TiCI pre-split for global sort ingest | tidb-test=13ccf8de48e8db2290ff884598444d0508606bbf tiflash=feature-fts Mar 24, 2026
@3pointer

Copy link
Copy Markdown
Contributor Author

/test mysql-test

@tiprow

tiprow Bot commented Mar 24, 2026

Copy link
Copy Markdown

@3pointer: PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test.

Details

In response to this:

/test mysql-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.

@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

🧹 Nitpick comments (2)
pkg/ddl/backfilling_dist_scheduler.go (2)

816-850: Consider using actual groupSize instead of estimated value.

Line 816 captures groupSize and groupKeyCnt from SplitOneRangesGroup() but ignores them. However, line 849 uses an estimated value kvMeta.TotalKVSize / uint64(instanceCnt) for TotalKVSize in the metadata.

The actual groupSize returned by the splitter would be more accurate. The TiCI pre-split code at line 738 correctly uses the actual groupSize.

♻️ Suggested improvement
-		endKeyOfGroup, dataFiles, statFiles, _, _, interiorRangeJobKeys, interiorRegionSplitKeys, err := splitter.SplitOneRangesGroup()
+		endKeyOfGroup, dataFiles, statFiles, groupSize, _, interiorRangeJobKeys, interiorRegionSplitKeys, err := splitter.SplitOneRangesGroup()
 		// ... existing code ...
 		m := &BackfillSubTaskMeta{
 			MetaGroups: []*external.SortedKVMeta{{
 				StartKey:    startKey,
 				EndKey:      endKey,
-				TotalKVSize: kvMeta.TotalKVSize / uint64(instanceCnt),
+				TotalKVSize: groupSize,
 			}},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/ddl/backfilling_dist_scheduler.go` around lines 816 - 850, The code calls
splitter.SplitOneRangesGroup() which returns groupSize but the value is ignored
and TotalKVSize in BackfillSubTaskMeta.MetaGroups is set to the coarse
kvMeta.TotalKVSize / uint64(instanceCnt); change this to use the actual
groupSize returned by SplitOneRangesGroup() (the identifier groupSize) when
constructing the MetaGroups entry in the BackfillSubTaskMeta to provide an
accurate TotalKVSize, i.e., replace the computed expression with groupSize
(casting if necessary to uint64) where TotalKVSize is assigned.

656-680: Failpoint and production code handle nil kvMeta differently.

The failpoint at lines 658-660 silently skips nil entries with continue, while the production code at line 680 returns an error. This inconsistency could mask bugs during testing where nil entries would silently succeed in tests but fail in production.

Consider aligning the behaviors or documenting this intentional difference.

♻️ Suggested fix for consistency
 	failpoint.Inject("mockBuildTiCIPreSplitReportGroups", func() {
 		reportGroups := make([]*tici.PreSplitImportShardMeta, 0, len(kvMetaGroups))
 		for i, kvMeta := range kvMetaGroups {
 			if kvMeta == nil {
-				continue
+				failpoint.Return(nil, errors.Errorf("subtask kv group %d is empty", i))
 			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/ddl/backfilling_dist_scheduler.go` around lines 656 - 680, The failpoint
Inject block (failpoint.Inject / mockBuildTiCIPreSplitReportGroups) currently
skips nil entries in kvMetaGroups while the production loop over kvMetaGroups
(where PreSplitImportShardMeta objects are built) returns an error on nil
kvMeta; make them consistent by changing the failpoint behavior to mirror
production: when iterating kvMetaGroups in the failpoint, detect nil kvMeta and
return an error (similar text to "subtask kv group %d is empty") instead of
silently continuing, so tests fail the same way as production; alternatively, if
you intended to allow nil entries, change the production loop to skip like the
failpoint—pick one approach and apply it to both the failpoint.Inject block and
the production loop that builds reportGroups (referencing kvMetaGroups, eleIDs,
and PreSplitImportShardMeta).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/ddl/backfilling_dist_scheduler.go`:
- Around line 178-186: The call to generateGlobalSortIngestPlan uses an
unchecked type assertion store.(storageWithPDAndCodec) which can panic; replace
it with a checked assertion (e.g., storeWithCodec, ok :=
store.(storageWithPDAndCodec)) and if !ok return an error (or wrap an existing
error type) indicating "store does not implement storageWithPDAndCodec" before
calling generateGlobalSortIngestPlan, then pass storeWithCodec into
generateGlobalSortIngestPlan instead of the direct assertion.

---

Nitpick comments:
In `@pkg/ddl/backfilling_dist_scheduler.go`:
- Around line 816-850: The code calls splitter.SplitOneRangesGroup() which
returns groupSize but the value is ignored and TotalKVSize in
BackfillSubTaskMeta.MetaGroups is set to the coarse kvMeta.TotalKVSize /
uint64(instanceCnt); change this to use the actual groupSize returned by
SplitOneRangesGroup() (the identifier groupSize) when constructing the
MetaGroups entry in the BackfillSubTaskMeta to provide an accurate TotalKVSize,
i.e., replace the computed expression with groupSize (casting if necessary to
uint64) where TotalKVSize is assigned.
- Around line 656-680: The failpoint Inject block (failpoint.Inject /
mockBuildTiCIPreSplitReportGroups) currently skips nil entries in kvMetaGroups
while the production loop over kvMetaGroups (where PreSplitImportShardMeta
objects are built) returns an error on nil kvMeta; make them consistent by
changing the failpoint behavior to mirror production: when iterating
kvMetaGroups in the failpoint, detect nil kvMeta and return an error (similar
text to "subtask kv group %d is empty") instead of silently continuing, so tests
fail the same way as production; alternatively, if you intended to allow nil
entries, change the production loop to skip like the failpoint—pick one approach
and apply it to both the failpoint.Inject block and the production loop that
builds reportGroups (referencing kvMetaGroups, eleIDs, and
PreSplitImportShardMeta).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac67be6-60bc-4336-be28-b475299249e3

📥 Commits

Reviewing files that changed from the base of the PR and between 0040136 and cf6bba6.

⛔ Files ignored due to path filters (1)
  • pkg/tici/tici.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (1)
  • pkg/ddl/backfilling_dist_scheduler.go

Comment thread pkg/ddl/backfilling_dist_scheduler.go

@OliverS929 OliverS929 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It looks like this PR may not cover all tici-index paths for global sort ingest yet. At the moment, only the DDL-related path seems to be implemented, while import-into does not appear to be included. If that is the intended scope, could we make it explicit in the PR description or comments?

Comment thread pkg/tici/tici.proto Outdated
rpc GetImportStoragePrefix(GetImportStoragePrefixRequest)
returns (GetImportStoragePrefixResponse);

// Called before Import Into full index build to pre-split shards by

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think this PR has included the pre-split support for Import Into related path. If that is beyond the scope of this PR, please change the comment accordingly and add an TODO item for Import Into support.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

comments updated

require.Equal(t, proto.StepDone, task.Step)
}

func TestBackfillingSchedulerGlobalSortModeTiCIPreSplit(t *testing.T) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If I understand this unit test correctly, this unit test has mockGenerateGlobalSortIngestPlanAfterPreSplit enabled, which actually skipped through the actual pre-split implementation, and thus does not provide coverage for the function implementation itself.

var lastEndKey []byte
notExhausted:
endKey, dataFiles, statFiles, rangeJobKeys, regionSplitKeys, err := splitter.SplitOneRangesGroup()
endKey, dataFiles, statFiles, _, _, rangeJobKeys, regionSplitKeys, err := splitter.SplitOneRangesGroup()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think directly shorting the return value here in this test file will provide coverage for the newly-introduced behavior of RangeSplitter.

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

1-13: Consider updating license year for new file.

This is a new file created in 2026, but uses "Copyright 2023" in the license header. Per coding guidelines, new source files should use the current year or match nearby conventions.

📝 Suggested fix
-// Copyright 2023 PingCAP, Inc.
+// Copyright 2025 PingCAP, Inc.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/ddl/backfilling_dist_scheduler_internal_test.go` around lines 1 - 13,
Update the license header year in the new test file
backfilling_dist_scheduler_internal_test.go to the current year (2026) or match
the surrounding project's convention; open the file header comment block and
replace "Copyright 2023" with the correct year so the file's license metadata is
accurate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/ddl/backfilling_dist_scheduler_internal_test.go`:
- Around line 1-13: Update the license header year in the new test file
backfilling_dist_scheduler_internal_test.go to the current year (2026) or match
the surrounding project's convention; open the file header comment block and
replace "Copyright 2023" with the correct year so the file's license metadata is
accurate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 987b71ae-0935-4d24-a033-8de66a3c9875

📥 Commits

Reviewing files that changed from the base of the PR and between cf6bba6 and 95acd09.

📒 Files selected for processing (6)
  • pkg/ddl/backfilling_dist_scheduler.go
  • pkg/ddl/backfilling_dist_scheduler_internal_test.go
  • pkg/ddl/backfilling_dist_scheduler_test.go
  • pkg/lightning/backend/external/split.go
  • pkg/lightning/backend/external/split_test.go
  • pkg/tici/tici.proto
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/ddl/backfilling_dist_scheduler_test.go

@ti-chi-bot

ti-chi-bot Bot commented Mar 25, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: GMHDBJD, OliverS929, wjhuang2016

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

@3pointer

Copy link
Copy Markdown
Contributor Author

/test pull-unit-test-ddlv1

@3pointer

Copy link
Copy Markdown
Contributor Author

/test fast_test_tiprow_for_release

@ti-chi-bot

ti-chi-bot Bot commented Mar 25, 2026

Copy link
Copy Markdown

@3pointer: 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-integration-e2e-test
/test pull-lightning-integration-test
/test pull-mysql-client-test
/test pull-unit-test-ddlv1
/test unit-test

The following commands are available to trigger optional jobs:

/test pingcap/tidb/canary_ghpr_unit_test
/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-jdbc-test
/test pull-integration-mysql-test
/test pull-integration-nodejs-test
/test pull-integration-python-orm-test
/test pull-integration-tici-test
/test pull-sqllogic-test
/test pull-tiflash-integration-test

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

pingcap/tidb/ghpr_build
pingcap/tidb/ghpr_check
pingcap/tidb/ghpr_check2
pingcap/tidb/ghpr_mysql_test
pingcap/tidb/ghpr_unit_test
pingcap/tidb/pull_br_integration_test
pingcap/tidb/pull_integration_e2e_test
pingcap/tidb/pull_integration_tici_test
pingcap/tidb/pull_lightning_integration_test
pingcap/tidb/pull_mysql_client_test
pingcap/tidb/pull_unit_test_ddlv1
Details

In response to this:

/test fast_test_tiprow_for_release

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.

@tiprow

tiprow Bot commented Mar 25, 2026

Copy link
Copy Markdown

@3pointer: PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test.

Details

In response to this:

/test pull-unit-test-ddlv1

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.

@tiprow

tiprow Bot commented Mar 25, 2026

Copy link
Copy Markdown

@3pointer: PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test.

Details

In response to this:

/test fast_test_tiprow_for_release

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.

@3pointer

Copy link
Copy Markdown
Contributor Author

/test pull-br-integration-test

@tiprow

tiprow Bot commented Mar 25, 2026

Copy link
Copy Markdown

@3pointer: PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test.

Details

In response to this:

/test pull-br-integration-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.

@3pointer

Copy link
Copy Markdown
Contributor Author

/ok-to-test

@ti-chi-bot ti-chi-bot Bot added the ok-to-test Indicates a PR is ready to be tested. label Mar 25, 2026
@3pointer

Copy link
Copy Markdown
Contributor Author

/test pull-integration-tici-test

@3pointer

Copy link
Copy Markdown
Contributor Author

/test pull-br-integration-test

@tiprow

tiprow Bot commented Mar 25, 2026

Copy link
Copy Markdown

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

/test fast_test_tiprow_for_release

Use /test all to run all jobs.

Details

In response to this:

/test pull-integration-tici-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.

@tiprow

tiprow Bot commented Mar 25, 2026

Copy link
Copy Markdown

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

/test fast_test_tiprow_for_release

Use /test all to run all jobs.

Details

In response to this:

/test pull-br-integration-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.

@3pointer

Copy link
Copy Markdown
Contributor Author

/test fast_test_tiprow_for_release

@ti-chi-bot

ti-chi-bot Bot commented Mar 26, 2026

Copy link
Copy Markdown

@3pointer: 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-integration-e2e-test
/test pull-lightning-integration-test
/test pull-mysql-client-test
/test pull-unit-test-ddlv1
/test unit-test

The following commands are available to trigger optional jobs:

/test pingcap/tidb/canary_ghpr_unit_test
/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-jdbc-test
/test pull-integration-mysql-test
/test pull-integration-nodejs-test
/test pull-integration-python-orm-test
/test pull-integration-tici-test
/test pull-sqllogic-test
/test pull-tiflash-integration-test

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

pingcap/tidb/ghpr_build
pingcap/tidb/ghpr_check
pingcap/tidb/ghpr_check2
pingcap/tidb/ghpr_mysql_test
pingcap/tidb/ghpr_unit_test
pingcap/tidb/pull_br_integration_test
pingcap/tidb/pull_integration_e2e_test
pingcap/tidb/pull_integration_tici_test
pingcap/tidb/pull_lightning_integration_test
pingcap/tidb/pull_mysql_client_test
pingcap/tidb/pull_unit_test_ddlv1
Details

In response to this:

/test fast_test_tiprow_for_release

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.

@tiprow

tiprow Bot commented Mar 26, 2026

Copy link
Copy Markdown

@3pointer: 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 d5434fb 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.

@ti-chi-bot
ti-chi-bot Bot merged commit 334fc4a into pingcap:feature/fts Mar 26, 2026
25 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved 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/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants