Skip to content

ingest: release unsent jobs when generateAndSendJob is canceled (#69241) - #70234

Open
ti-chi-bot wants to merge 1 commit into
pingcap:release-8.5from
ti-chi-bot:cherry-pick-69241-to-release-8.5
Open

ingest: release unsent jobs when generateAndSendJob is canceled (#69241)#70234
ti-chi-bot wants to merge 1 commit into
pingcap:release-8.5from
ti-chi-bot:cherry-pick-69241-to-release-8.5

Conversation

@ti-chi-bot

@ti-chi-bot ti-chi-bot commented Jul 30, 2026

Copy link
Copy Markdown
Member

This is an automated cherry-pick of #69241

What problem does this PR solve?

Issue Number: close #69240

Problem Summary:

PR #64767 changed generateAndSendJob to ref all generated region jobs before sending any of them to jobToWorkerCh. That protects shared ingest data from being cleaned too early, but it left a cancellation gap: if the context is canceled after one job is sent and before the remaining jobs in the same slice are sent, only the current unsent job is marked done. Later jobs were already refed but are never handed to a downstream owner and never marked done, so jobWg.Wait() can block forever and keep RunSubtask stuck.

What changed and how does it work?

When generateAndSendJob observes context cancellation in the send loop, it now marks every remaining unsent job in jobs[i:] as done before returning. Jobs before i were already sent to jobToWorkerCh and remain owned by downstream components. The current job and later jobs were not sent, so the generator must balance their earlier refs locally.

The new unit test reproduces the stuck path by sending the first generated job, canceling the context, and asserting that jobWg.Wait() still finishes after generateAndSendJob returns.

Check List

Tests

  • Unit test
    • ./tools/check/failpoint-go-test.sh pkg/ingestor/ingestctrl -run TestGenerateAndSendJobDoneAllRefedJobsOnCancel -count=1 failed before the fix with jobWg.Wait should finish after generateAndSendJob returns.
    • ./tools/check/failpoint-go-test.sh pkg/ingestor/ingestctrl -run 'Test(GenerateAndSendJobDoneAllRefedJobsOnCancel|RefAllJobsBeforeSending)$' -count=1
    • make lint
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

Side effects

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

Documentation

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

Release note

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

Fix a bug that could cause IMPORT INTO or related local backend ingest tasks to hang after job generation was canceled.

Summary by CodeRabbit

  • Bug Fixes

    • Improved job cancellation handling to ensure all unsent jobs are properly cleaned up.
    • Prevented reference-counted ingest data from remaining active after a canceled operation.
  • Tests

    • Added coverage verifying reference-count cleanup when job generation is canceled mid-process.

Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
@ti-chi-bot ti-chi-bot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. type/cherry-pick-for-release-8.5 This PR is cherry-picked to release-8.5 from a source PR. labels Jul 30, 2026
@ti-chi-bot

Copy link
Copy Markdown
Member Author

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

@ti-chi-bot

ti-chi-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

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

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository.

@ti-chi-bot

ti-chi-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

[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 benjamin2037 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

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

generateAndSendJob now releases references for all jobs left unsent after cancellation. A regression test verifies that refcount cleanup completes and the associated wait group does not remain blocked.

Changes

Cancellation Refcount Cleanup

Layer / File(s) Summary
Release unsent jobs on cancellation
pkg/lightning/backend/local/local.go, pkg/lightning/backend/local/local_test.go
The cancellation path marks all remaining generated jobs as done, while a regression test validates refcount cleanup after the first job is sent and cancellation occurs. The test comment now identifies engineapi.Engine.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit watched the workers go,
One job sent, then winds would blow.
The waiting refs all hopped away,
No dangling paws remained to stay.
“Done!” cried Bunny—“clean as hay!”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main fix: releasing unsent jobs when cancellation interrupts generateAndSendJob.
Description check ✅ Passed The description includes the issue number, problem summary, implementation details, tests, and a release note.
Linked Issues check ✅ Passed The change matches #69240 by balancing refs for all unsent jobs on cancellation and adds a test for the hang scenario.
Out of Scope Changes check ✅ Passed The PR stays focused on the cancellation bug fix and related test/comment updates, with no clear unrelated changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

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

🔧 golangci-lint (2.12.2)

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


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@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/lightning/backend/local/local_test.go`:
- Around line 2789-2854: Resolve the conflict markers around
TestGenerateAndSendJobDoneAllRefedJobsOnCancel and mockEngineWithData, retaining
the incoming test and surrounding declarations exactly once. Update the test’s
testfailpoint.Enable path to pkg/lightning/backend/local/fakeRegionJobs,
matching the package’s established fakeRegionJobs hook, and remove all conflict
markers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 98e8c7f1-6123-4237-a23f-6ef846e2eb37

📥 Commits

Reviewing files that changed from the base of the PR and between 0d2e635 and 613342c.

📒 Files selected for processing (2)
  • pkg/lightning/backend/local/local.go
  • pkg/lightning/backend/local/local_test.go

Comment on lines +2789 to +2854
<<<<<<< HEAD:pkg/lightning/backend/local/local_test.go
// mockEngineWithData is a mock engine that implements common.Engine
=======
func TestGenerateAndSendJobDoneAllRefedJobsOnCancel(t *testing.T) {
testfailpoint.Enable(t, "github.com/pingcap/tidb/pkg/ingestor/ingestctrl/fakeRegionJobs", "return()")

ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
local := &Backend{}
local.WorkerConcurrency.Store(1)

data := &refCountIngestData{
mockIngestData: mockIngestData{
{[]byte("b"), []byte("b")},
{[]byte("c"), []byte("c")},
{[]byte("d"), []byte("d")},
{[]byte("e"), []byte("e")},
},
}
jobs := []*regionJob{
{keyRange: engineapi.Range{Start: []byte("a"), End: []byte("b")}, ingestData: data, region: dummyRegionInfo},
{keyRange: engineapi.Range{Start: []byte("b"), End: []byte("c")}, ingestData: data, region: dummyRegionInfo},
{keyRange: engineapi.Range{Start: []byte("c"), End: []byte("d")}, ingestData: data, region: dummyRegionInfo},
{keyRange: engineapi.Range{Start: []byte("d"), End: []byte("e")}, ingestData: data, region: dummyRegionInfo},
}
jobRange := engineapi.Range{Start: []byte("a"), End: []byte("e")}
fakeRegionJobs = map[[2]string]struct {
jobs []*regionJob
err error
}{
{"a", "e"}: {
jobs: jobs,
},
}
t.Cleanup(func() {
fakeRegionJobs = nil
})

mockEngine := &mockEngineWithData{
data: data,
ranges: []engineapi.Range{jobRange},
}
jobToWorkerCh := make(chan *regionJob)
var jobWg sync.WaitGroup
firstJobDone := make(chan struct{})

go func() {
job := <-jobToWorkerCh
job.done(&jobWg)
cancel()
close(firstJobDone)
}()

err := local.generateAndSendJob(ctx, mockEngine, int64(config.SplitRegionSize), int64(config.SplitRegionKeys), jobToWorkerCh, &jobWg)
require.NoError(t, err)
<-firstJobDone

require.Eventually(t, func() bool {
return data.GetRefCount() == 0
}, 10*time.Second, 10*time.Millisecond, "ref'd jobs after the canceled send path must all be marked done")
jobWg.Wait()
require.Equal(t, int64(0), data.GetRefCount())
}

// mockEngineWithData is a mock engine that implements engineapi.Engine
>>>>>>> 9f9c4f8b763 (ingest: release unsent jobs when generateAndSendJob is canceled (#69241)):pkg/ingestor/ingestctrl/local_test.go

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Resolve the unreconciled cherry-pick conflict.

<<<<<<<, =======, and >>>>>>> make this package uncompilable. When retaining the incoming test, change its failpoint path to pkg/lightning/backend/local/fakeRegionJobs; the current pkg/ingestor/ingestctrl/... path does not match this package’s established fake-job hook.

🤖 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/lightning/backend/local/local_test.go` around lines 2789 - 2854, Resolve
the conflict markers around TestGenerateAndSendJobDoneAllRefedJobsOnCancel and
mockEngineWithData, retaining the incoming test and surrounding declarations
exactly once. Update the test’s testfailpoint.Enable path to
pkg/lightning/backend/local/fakeRegionJobs, matching the package’s established
fakeRegionJobs hook, and remove all conflict markers.

Source: Coding guidelines

@ti-chi-bot

ti-chi-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

@ti-chi-bot: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
idc-jenkins-ci-tidb/unit-test 613342c link true /test unit-test
idc-jenkins-ci-tidb/check_dev 613342c link true /test check-dev
idc-jenkins-ci-tidb/build 613342c link true /test build
idc-jenkins-ci-tidb/check_dev_2 613342c link true /test check-dev2

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 added cherry-pick-approved Cherry pick PR approved by release team. and removed do-not-merge/cherry-pick-not-approved labels Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cherry-pick-approved Cherry pick PR approved by release team. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. type/cherry-pick-for-release-8.5 This PR is cherry-picked to release-8.5 from a source PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants