Skip to content

localbackend: add write timeout handling for object store region jobs - #68148

Merged
ti-chi-bot[bot] merged 7 commits into
pingcap:masterfrom
D3Hunter:codex/lightning-write-timeout-handling-61702
May 7, 2026
Merged

ti-chi-bot[bot] merged 7 commits into
pingcap:masterfrom
D3Hunter:codex/lightning-write-timeout-handling-61702

Conversation

@D3Hunter

@D3Hunter D3Hunter commented May 1, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: ref #61702

Problem Summary:

Object store imports use the object store region job worker, which can time out while creating or using the TiKV write client. The write timeout handling was tied to Backend.doWrite, so object store region jobs did not get the same common.ErrWriteTooSlow retry behavior before runJob classified write errors.

What changed and how does it work?

Move the 15-minute write timeout wrapper to regionJobBaseWorker.writeWithTimeout, so both local backend writes and object store region job worker writes are wrapped before runJob classifies retryable write errors. If the context deadline is caused by common.ErrWriteTooSlow, return that error so the job is marked retryable and can be rescanned/retried.

Remove the duplicate timeout wrapper from Backend.doWrite and keep the existing short write-timeout failpoint setup. This keeps the timeout behavior in the common region job execution path instead of only in the local backend write implementation.

Check List

Tests

  • Unit test
    • ./tools/check/failpoint-go-test.sh pkg/lightning/backend/local -run 'Test(CloudRegionJobWorker|RegionJobBaseWorker)$' -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.

Improve TiDB Lightning object store region job retry handling when writes to TiKV exceed the write timeout.

Summary by CodeRabbit

  • Bug Fixes

    • Improved TiKV write timeout handling to better detect, log, and trace slow writes while preserving retry behavior; added an opt-in path to simulate shorter per-write timeouts.
  • Tests

    • Added/updated tests for write-timeout and retry scenarios, including a client-creation timeout case.
    • Updated log assertion to expect “TiKV” capitalization in timeout messages.

@ti-chi-bot ti-chi-bot Bot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label May 1, 2026
@pantheon-ai

pantheon-ai Bot commented May 1, 2026 •

Copy link
Copy Markdown

@D3Hunter I've received your pull request and will start the review. I'll conduct a thorough review covering code quality, potential issues, and implementation details.

⏳ This process typically takes 10-30 minutes depending on the complexity of the changes.

ℹ️ Learn more details on Pantheon AI.

@ti-chi-bot ti-chi-bot Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label May 1, 2026
@tiprow

tiprow Bot commented May 1, 2026

Copy link
Copy Markdown

Hi @D3Hunter. 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.

@coderabbitai

coderabbitai Bot commented May 1, 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 a per-write timeout wrapper writeWithTimeout used by region job workers, removes the prior unconditional 15-minute timeout from the write path (leaving a failpoint hook for shorter per-call timeouts), updates call sites to use the wrapper, and extends unit/integration tests and imports to support timeout-cause detection.

Changes

Write timeout refactor and test updates

Layer / File(s) Summary
Imports / Data shape
pkg/lightning/backend/local/job_worker.go
Adds import alias goerrors "errors" for errors.Is comparisons against timeout causes.
Wrapper introduced
pkg/lightning/backend/local/job_worker.go
Adds regionJobBaseWorker.writeWithTimeout(ctx, job) which runs writes under a 15-minute timeout, supports a shorter failpoint-injected timeout, uses context.WithTimeoutCause, inspects context.Cause with errors.Is to map deadline causes (e.g., common.ErrWriteTooSlow), and delegates to the existing w.writeFn.
Callsite update
pkg/lightning/backend/local/job_worker.go
runJob now calls w.writeWithTimeout(ctx, job) instead of calling the underlying write directly.
Failpoint wiring / removal of unconditional timeout
pkg/lightning/backend/local/region_job.go
Removes the previous unconditional 15-minute WithTimeoutCause/translation; adds a failpoint-backed shortWaitNTimeout path that can create a per-call wctx/wcancel (guarded by failpoint) and a small failpoint delay in flushKVs; writeLimiter.WaitN is left using the original ctx.
Unit test
pkg/lightning/backend/local/job_worker_test.go
Adds a test case verifying runJob handles ingest-client creation timing out: simulates WriteClient deadline, maps the deadline cause to common.ErrWriteTooSlow, expects runJob to suppress the error, mark job for rescanning, and record lastRetryableErr.
Integration test script tweak
lightning/tests/lightning_write_timeout/run.sh
Enables the shorter timeout failpoint via GO_FAILPOINTS change and adjusts the log expectation text for the TiKV timeout message.

Sequence Diagram(s)

sequenceDiagram
    participant Worker as Worker.runJob
    participant Wrapper as writeWithTimeout
    participant Limiter as writeLimiter
    participant TiKV as TiKV / ingest client

    Worker->>Wrapper: writeWithTimeout(ctx, job)
    Wrapper->>Limiter: WaitN(ctx, storeID, size)
    Limiter-->>Wrapper: permit/deny
    alt failpoint injects short timeout
        Wrapper->>TiKV: w.writeFn using wctx (timed)
    else default
        Wrapper->>TiKV: w.writeFn using ctx
    end
    TiKV-->>Wrapper: success or deadline exceeded (with cause)
    Wrapper->>Worker: return result (or translated retryable timeout)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

size/XL

Suggested reviewers

  • joechenrh
  • wjhuang2016
  • Benjamin2037

Poem

🐰 I nudged a timeout into the write,
Wrapped contexts softly through day and night.
Failpoints whisper short alarms,
Limiters hum and TiKV charms—
Tests dance, and logs glow bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 accurately describes the main change: adding write timeout handling for object store region jobs, which is the core purpose of moving the timeout wrapper.
Description check ✅ Passed The description follows the template structure, includes a referenced issue, clearly explains the problem and solution, lists unit tests performed, and provides a release note.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@D3Hunter D3Hunter changed the title lightning: unify write timeout handling for region jobs lightning: add write timeout handling for object store region jobs May 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/lightning/backend/local/job_worker_test.go (1)

309-326: ⚡ Quick win

Add one more timeout case for the write stream itself.

This subtest only exercises timeout during WriteClient creation. Since the wrapper is meant to cover the whole TiKV write path, please add a case where WriteClient succeeds and Write or Recv times out as well.

🔧 Suggested test shape
+	t.Run("timeout while writing or receiving should be handled by runJob wrapper", func(t *testing.T) {
+		// Arrange a mock write client that succeeds on creation,
+		// then blocks or returns context.DeadlineExceeded from Write/Recv.
+	})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/lightning/backend/local/job_worker_test.go` around lines 309 - 326, Add a
sibling subtest that simulates a timeout on the write stream (not just
WriteClient creation): in addition to the existing test using
mockIngestCli.EXPECT().WriteClient(...).Return(nil, context.DeadlineExceeded),
add a test where mockIngestCli.EXPECT().WriteClient(...).Return(mockWriteClient,
nil) and configure mockWriteClient.EXPECT().Write(...) or
mockWriteClient.EXPECT().Recv(...).Return(context.DeadlineExceeded) (or both) to
simulate the stream timing out; call cloudW.runJob(ctx, job) with a context
created via context.WithTimeoutCause(..., common.ErrWriteTooSlow) and assert the
same outcomes as the current test (require.NoError on runJob, job.stage ==
needRescan, job.lastRetryableErr is common.ErrWriteTooSlow, and
ctrl.Satisfied()).
🤖 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/lightning/backend/local/job_worker_test.go`:
- Around line 309-326: Add a sibling subtest that simulates a timeout on the
write stream (not just WriteClient creation): in addition to the existing test
using mockIngestCli.EXPECT().WriteClient(...).Return(nil,
context.DeadlineExceeded), add a test where
mockIngestCli.EXPECT().WriteClient(...).Return(mockWriteClient, nil) and
configure mockWriteClient.EXPECT().Write(...) or
mockWriteClient.EXPECT().Recv(...).Return(context.DeadlineExceeded) (or both) to
simulate the stream timing out; call cloudW.runJob(ctx, job) with a context
created via context.WithTimeoutCause(..., common.ErrWriteTooSlow) and assert the
same outcomes as the current test (require.NoError on runJob, job.stage ==
needRescan, job.lastRetryableErr is common.ErrWriteTooSlow, and
ctrl.Satisfied()).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: dec71dd6-294d-402d-aecd-636198057c17

📥 Commits

Reviewing files that changed from the base of the PR and between 9d1ac81 and f2f9739.

📒 Files selected for processing (3)
  • pkg/lightning/backend/local/job_worker.go
  • pkg/lightning/backend/local/job_worker_test.go
  • pkg/lightning/backend/local/region_job.go

@codecov

codecov Bot commented May 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.5461%. Comparing base (9d1ac81) to head (f4cb5fb).
⚠️ Report is 20 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #68148        +/-   ##
================================================
- Coverage   77.7620%   77.5461%   -0.2160%     
================================================
  Files          1990       1984         -6     
  Lines        551774     558840      +7066     
================================================
+ Hits         429071     433359      +4288     
- Misses       121783     124557      +2774     
- Partials        920        924         +4     
Flag Coverage Δ
integration 43.8877% <100.0000%> (+4.0858%) ⬆️

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

Components Coverage Δ
dumpling 60.4888% <ø> (ø)
parser ∅ <ø> (∅)
br 50.0597% <ø> (-13.0338%) ⬇️
🚀 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.

@ingress-bot

Copy link
Copy Markdown

🔍 Starting code review for this PR...

@ingress-bot ingress-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.

This review was generated by AI and should be verified by a human reviewer.
Manual follow-up is recommended before merge.

Summary

  • Total findings: 3
  • Inline comments: 3
  • Summary-only findings (no inline anchor): 0
Findings (highest risk first)

🟡 [Minor] (3)

  1. doWrite comment still points to a removed timeout defer location (pkg/lightning/backend/local/job_worker.go:270, pkg/lightning/backend/local/region_job.go:501)
  2. Write-timeout regression signal became nondeterministic for the shortWaitNTimeout path (pkg/lightning/backend/local/job_worker.go:283, pkg/lightning/backend/local/region_job.go:461, lightning/tests/lightning_write_timeout/run.sh:48)
  3. doWrite timeout comment now describes removed control flow (pkg/lightning/backend/local/region_job.go:501, pkg/lightning/backend/local/job_worker.go:270)

Comment thread pkg/lightning/backend/local/job_worker.go
Comment thread pkg/lightning/backend/local/job_worker.go
Comment thread pkg/lightning/backend/local/region_job.go Outdated
@D3Hunter

D3Hunter commented May 1, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented May 1, 2026

Copy link
Copy Markdown

@D3Hunter: 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:

/retest

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.

@D3Hunter

D3Hunter commented May 1, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented May 1, 2026

Copy link
Copy Markdown

@D3Hunter: 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:

/retest

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.

@D3Hunter D3Hunter changed the title lightning: add write timeout handling for object store region jobs localbackend: add write timeout handling for object store region jobs May 6, 2026
@D3Hunter

D3Hunter commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented May 6, 2026

Copy link
Copy Markdown

@D3Hunter: 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:

/retest

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 size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels May 6, 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 (2)
pkg/lightning/backend/local/region_job.go (1)

469-484: 💤 Low value

Stale comment at lines 469–471 references a removed failpoint context.

The two-line comment "original ctx would be used when failpoint is not enabled / that new context would be used when failpoint is enabled" no longer matches this function. The shortWaitNTimeout failpoint, which previously injected a separate write context here, has been moved to regionJobBaseWorker.writeWithTimeout in job_worker.go. doWrite now only sees a single ctx, so the contrast described in the comment is misleading for future readers tracing the timeout-injection path.

Consider dropping or simplifying that pair of lines, e.g.:

📝 Proposed comment cleanup
-			// original ctx would be used when failpoint is not enabled
-			// that new context would be used when failpoint is enabled
 			err := writeLimiter.WaitN(ctx, allPeers[i].StoreId, int(size))
 			if err != nil {
 				// We expect to encounter two types of errors here:
 				// 1. context.DeadlineExceeded — occurs when the calculated delay is
 				//    less than the remaining time in the context, but the context
 				//    expires while sleeping.
 				// 2. "rate: Wait(n=%d) would exceed context deadline" — a fast-fail
 				//    path triggered when the delay already exceeds the remaining
 				//    time for context before sleeping.
 				//
-				// "rate: Wait" error is already treated as retryable,
-				// writeWithTimeout will handle the context.DeadlineExceeded.
+				// The "rate: Wait" error is already treated as retryable;
+				// context.DeadlineExceeded is translated to common.ErrWriteTooSlow
+				// by regionJobBaseWorker.writeWithTimeout in runJob.
 				return errors.Trace(err)
 			}
🤖 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/region_job.go` around lines 469 - 484, The
two-line comment in doWrite that claims "original ctx would be used when
failpoint is not enabled / that new context would be used when failpoint is
enabled" is stale because the shortWaitNTimeout failpoint was moved into
regionJobBaseWorker.writeWithTimeout (job_worker.go) and doWrite now only
receives a single ctx; remove or replace those two lines with a concise note
that timeout injection is handled in writeWithTimeout (or simply delete the
misleading lines) so readers are not misled about multiple contexts in doWrite.
pkg/lightning/backend/local/job_worker.go (1)

290-295: ⚡ Quick win

Use goerrors.Is(err, context.DeadlineExceeded) instead of errors.Cause(err) == for consistency and robustness.

Line 290 uses errors.Cause(err) == context.DeadlineExceeded, which only unwraps errors via the pingcap/errors Cause() interface. This misses errors wrapped with Go's standard fmt.Errorf("...: %w", ...) pattern (common in gRPC), allowing deadline timeouts to leak through uncaught. The codebase already uses goerrors.Is() for context sentinel checks elsewhere (e.g., log.go, retry.go, byte_reader.go), and line 291 in this same block already uses goerrors.Is() for a similar cause check.

Proposed change
-	if errors.Cause(err) == context.DeadlineExceeded {
+	if goerrors.Is(err, context.DeadlineExceeded) {
 		if cause := context.Cause(ctx); goerrors.Is(cause, common.ErrWriteTooSlow) {
 			tidblogutil.Logger(ctx).Info("Experiencing a wait timeout while writing to TiKV")
 			err = errors.Trace(cause)
 		}
 	}
🤖 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/job_worker.go` around lines 290 - 295, Replace
the equality check using errors.Cause(err) with the Go errors package helper so
deadline errors wrapped with %w are recognized: in the block that currently
tests errors.Cause(err) == context.DeadlineExceeded (the one that also inspects
context.Cause(ctx) and goerrors.Is(cause, common.ErrWriteTooSlow) and logs via
tidblogutil.Logger), change the condition to use goerrors.Is(err,
context.DeadlineExceeded) so wrapped deadline errors are correctly detected and
the existing handling (logging and err = errors.Trace(cause)) remains unchanged.
🤖 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/lightning/backend/local/job_worker.go`:
- Around line 290-295: Replace the equality check using errors.Cause(err) with
the Go errors package helper so deadline errors wrapped with %w are recognized:
in the block that currently tests errors.Cause(err) == context.DeadlineExceeded
(the one that also inspects context.Cause(ctx) and goerrors.Is(cause,
common.ErrWriteTooSlow) and logs via tidblogutil.Logger), change the condition
to use goerrors.Is(err, context.DeadlineExceeded) so wrapped deadline errors are
correctly detected and the existing handling (logging and err =
errors.Trace(cause)) remains unchanged.

In `@pkg/lightning/backend/local/region_job.go`:
- Around line 469-484: The two-line comment in doWrite that claims "original ctx
would be used when failpoint is not enabled / that new context would be used
when failpoint is enabled" is stale because the shortWaitNTimeout failpoint was
moved into regionJobBaseWorker.writeWithTimeout (job_worker.go) and doWrite now
only receives a single ctx; remove or replace those two lines with a concise
note that timeout injection is handled in writeWithTimeout (or simply delete the
misleading lines) so readers are not misled about multiple contexts in doWrite.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a5a48b9d-3cef-49f2-85a3-3b963669c0fb

📥 Commits

Reviewing files that changed from the base of the PR and between f2f9739 and 4a06c1f.

📒 Files selected for processing (3)
  • lightning/tests/lightning_write_timeout/run.sh
  • pkg/lightning/backend/local/job_worker.go
  • pkg/lightning/backend/local/region_job.go

@joechenrh joechenrh 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.

Rest LGTM

failpoint.Inject("shortWaitNTimeout", func(val failpoint.Value) {
ms := val.(int)
innerTimeout := time.Duration(ms) * time.Millisecond
tidblogutil.Logger(ctx).Info("Injecting a timeout to write context.")

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.

Suggested change
tidblogutil.Logger(ctx).Info("Injecting a timeout to write context.")
tidblogutil.Logger(ctx).Info("injecting a timeout to write context.")

}
if errors.Cause(err) == context.DeadlineExceeded {
if cause := context.Cause(ctx); goerrors.Is(cause, common.ErrWriteTooSlow) {
tidblogutil.Logger(ctx).Info("Experiencing a wait timeout while writing to TiKV")

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.

Suggested change
tidblogutil.Logger(ctx).Info("Experiencing a wait timeout while writing to TiKV")
tidblogutil.Logger(ctx).Info("experiencing a wait timeout while writing to TiKV")

@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label May 6, 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

🧹 Nitpick comments (1)
pkg/lightning/backend/local/region_job.go (1)

473-475: 💤 Low value

Stale comment: there is no separate "new context" anymore.

The comment on lines 474-475 still describes the prior design where the failpoint produced a separate timeout context for WaitN. In the current implementation the failpoint only does time.Sleep, and writeLimiter.WaitN always uses the same ctx regardless of whether the failpoint is enabled. Recommend removing or rewording so the intent (sleep long enough for the wrapper's ctx to expire and surface DeadlineExceeded) is what's documented.

♻️ Suggested rewording
-		for i := range clients {
-			// original ctx would be used when failpoint is not enabled
-			// that new context would be used when failpoint is enabled
-			err := writeLimiter.WaitN(ctx, allPeers[i].StoreId, int(size))
+		for i := range clients {
+			// When shortWaitNTimeout is enabled, the sleep above is long enough
+			// for ctx (already wrapped with a timeout in writeWithTimeout) to
+			// expire here, surfacing DeadlineExceeded from WaitN.
+			err := writeLimiter.WaitN(ctx, allPeers[i].StoreId, int(size))

As per coding guidelines, "Comments SHOULD explain non-obvious intent ... and SHOULD NOT restate what the code already makes clear."

🤖 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/region_job.go` around lines 473 - 475, The
existing comment near the loop over clients describing a "new context" is
stale—update the comment around the loop that references failpoint and
writeLimiter.WaitN to remove the mention of a separate context and instead state
the actual intent: the failpoint only does time.Sleep so it delays long enough
for the wrapper's ctx to expire and surface a context.DeadlineExceeded from
writeLimiter.WaitN; briefly document that behavior (or remove the comment
entirely) and reference the failpoint, the loop that iterates over clients, and
writeLimiter.WaitN so readers can find the related code.
🤖 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/job_worker.go`:
- Around line 289-290: Replace the direct comparison errors.Cause(err) ==
context.DeadlineExceeded with a call to goerrors.Is to consistently detect
deadline errors even when wrapped; specifically, in job_worker.go where the code
checks errors.Cause(err) == context.DeadlineExceeded (near the block that then
inspects context.Cause via goerrors.Is), change that condition to
goerrors.Is(err, context.DeadlineExceeded) so the deadline check uses the same
robust unwrapping semantics as the subsequent goerrors.Is usage.

---

Nitpick comments:
In `@pkg/lightning/backend/local/region_job.go`:
- Around line 473-475: The existing comment near the loop over clients
describing a "new context" is stale—update the comment around the loop that
references failpoint and writeLimiter.WaitN to remove the mention of a separate
context and instead state the actual intent: the failpoint only does time.Sleep
so it delays long enough for the wrapper's ctx to expire and surface a
context.DeadlineExceeded from writeLimiter.WaitN; briefly document that behavior
(or remove the comment entirely) and reference the failpoint, the loop that
iterates over clients, and writeLimiter.WaitN so readers can find the related
code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fc74ca53-2705-4171-ba10-66991b2dc871

📥 Commits

Reviewing files that changed from the base of the PR and between 1226785 and f4cb5fb.

📒 Files selected for processing (3)
  • lightning/tests/lightning_write_timeout/run.sh
  • pkg/lightning/backend/local/job_worker.go
  • pkg/lightning/backend/local/region_job.go

Comment on lines +289 to +290
if errors.Cause(err) == context.DeadlineExceeded {
if cause := context.Cause(ctx); goerrors.Is(cause, common.ErrWriteTooSlow) {

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect how writeFn implementations propagate context.DeadlineExceeded.
rg -nP -C3 '\bfunc\s+\([^)]*\)\s+(doWrite|write)\s*\(' pkg/lightning/backend/local
rg -nP -C2 'DeadlineExceeded|status\.FromContextError|context\.Cause' pkg/lightning/backend/local pkg/ingestor

Repository: pingcap/tidb

Length of output: 3167


🏁 Script executed:

# First, let's examine the doWrite function implementation
sed -n '331,450p' pkg/lightning/backend/local/region_job.go | head -100

Repository: pingcap/tidb

Length of output: 3077


🏁 Script executed:

# Examine the write function implementation
sed -n '355,420p' pkg/lightning/backend/local/job_worker.go

Repository: pingcap/tidb

Length of output: 1741


🏁 Script executed:

# Check how errors are imported and used in these files
head -50 pkg/lightning/backend/local/job_worker.go | grep -E 'import|errors|goerrors'

Repository: pingcap/tidb

Length of output: 164


🏁 Script executed:

# Look for gRPC status error handling in the codebase
rg -n 'status\.FromContextError|status\.FromError' pkg/lightning/backend/local pkg/ingestor

Repository: pingcap/tidb

Length of output: 141


🏁 Script executed:

# Get full context around job_worker.go:289-290
sed -n '270,310p' pkg/lightning/backend/local/job_worker.go

Repository: pingcap/tidb

Length of output: 1425


🏁 Script executed:

# Check if errors are wrapped with %w anywhere in writeFn implementations
rg '%w' pkg/lightning/backend/local/job_worker.go pkg/lightning/backend/local/region_job.go

Repository: pingcap/tidb

Length of output: 38


🏁 Script executed:

# Look for where gRPC stream errors might be handled before reaching line 289
sed -n '270,350p' pkg/lightning/backend/local/job_worker.go | grep -A30 'func (w \*localRegionJobWorker)'

Repository: pingcap/tidb

Length of output: 38


🏁 Script executed:

# Check how writeWithTimeout works and what writeFn is
sed -n '250,290p' pkg/lightning/backend/local/job_worker.go

Repository: pingcap/tidb

Length of output: 1392


🏁 Script executed:

# Check if pingcap/errors types implement Unwrap() for Is() compatibility
rg -n 'func.*Unwrap|func.*Cause' pkg/vendor/github.com/pingcap/errors 2>/dev/null || \
  rg -n 'pingcap/errors' go.mod

Repository: pingcap/tidb

Length of output: 125


🏁 Script executed:

# Look for any %w wrapping in region_job.go doWrite implementation
sed -n '331,550p' pkg/lightning/backend/local/region_job.go | grep -n '%w\|Wrap'

Repository: pingcap/tidb

Length of output: 38


🏁 Script executed:

# Check what Annotate and Trace functions do
rg -A5 'func.*Annotate|func.*Trace' pkg/lightning/backend/local/job_worker.go | head -20

Repository: pingcap/tidb

Length of output: 38


🏁 Script executed:

# Look at the complete doWrite to see all error returns
sed -n '331,600p' pkg/lightning/backend/local/region_job.go | grep -n 'return.*error\|errors\.\|err :='

Repository: pingcap/tidb

Length of output: 1077


🏁 Script executed:

# Check if there are any gRPC status error wrappings in doWrite
sed -n '331,600p' pkg/lightning/backend/local/region_job.go | grep -n 'status\|Status'

Repository: pingcap/tidb

Length of output: 38


🏁 Script executed:

# Look at the test to understand expected behavior
sed -n '310,330p' pkg/lightning/backend/local/job_worker_test.go

Repository: pingcap/tidb

Length of output: 945


🏁 Script executed:

# Check if pingcap/errors is implemented with Unwrap support by looking at actual usage patterns in tests
rg -B5 -A5 'goerrors\.Is.*DeadlineExceeded' pkg/lightning/backend/local/

Repository: pingcap/tidb

Length of output: 38


🏁 Script executed:

# Let's check the actual implementation path for how errors flow through WriteClient
rg -n 'WriteClient' pkg/lightning/backend/local/job_worker.go | head -5

Repository: pingcap/tidb

Length of output: 131


🏁 Script executed:

# Look at ingestCli to see what WriteClient returns
find pkg -name '*ingest*' -type f | head -10

Repository: pingcap/tidb

Length of output: 173


🏁 Script executed:

# Check how errors.Trace wraps errors - does it implement Unwrap?
rg -B3 -A10 'type.*Error|func.*Unwrap' pkg/vendor/github.com/pingcap/errors/errors.go 2>/dev/null || \
  python3 << 'EOF'
# Try to understand if pingcap/errors preserves error chains
import subprocess
result = subprocess.run(['find', 'pkg', '-name', 'errors.go', '-path', '*/pingcap/errors/*'], capture_output=True, text=True)
print("Found error files:")
print(result.stdout)
EOF

Repository: pingcap/tidb

Length of output: 76


🏁 Script executed:

# Let's check the ingestcli WriteClient implementation to see what errors it returns
sed -n '1,50p' pkg/ingestor/ingestcli/ingest_err.go

Repository: pingcap/tidb

Length of output: 1539


🏁 Script executed:

# Check what WriteClient interface/method looks like
rg -B5 -A10 'WriteClient.*func' pkg/ingestor/

Repository: pingcap/tidb

Length of output: 38


🏁 Script executed:

# Most importantly, let's verify if pingcap/errors implements Unwrap for goerrors.Is compatibility
python3 << 'EOF'
# Check if pingcap/errors in go.mod and look for its implementation
import subprocess
import os

# Find pingcap/errors package in vendor
result = subprocess.run(
    ['find', 'pkg/vendor/github.com/pingcap/errors', '-name', '*.go'],
    capture_output=True, text=True
)

if result.stdout:
    files = result.stdout.strip().split('\n')[:3]
    for f in files:
        print(f"\n=== {f} ===")
        with open(f) as fp:
            content = fp.read()
            # Look for Unwrap method
            if 'Unwrap' in content:
                lines = content.split('\n')
                for i, line in enumerate(lines):
                    if 'Unwrap' in line:
                        start = max(0, i-2)
                        end = min(len(lines), i+8)
                        print('\n'.join(lines[start:end]))
                        print('---')
EOF

Repository: pingcap/tidb

Length of output: 38


🏁 Script executed:

# Final check: verify the fix would work by checking if errors.Trace returns an error that satisfies goerrors.Is
rg -n 'func.*Trace.*error' pkg/ | grep pingcap || \
  grep -r 'func.*Trace' pkg/vendor/github.com/pingcap/errors/ 2>/dev/null | head -5

Repository: pingcap/tidb

Length of output: 38


Use goerrors.Is for consistent and robust deadline checking.

Line 289 uses errors.Cause(err) == context.DeadlineExceeded while line 290 already uses goerrors.Is. The current code relies on pingcap/errors to properly unwrap context.DeadlineExceeded, but future code could wrap errors using Go 1.13's %w operator or other patterns that bypass errors.Cause(). Using goerrors.Is(err, context.DeadlineExceeded) handles both current and future wrapping patterns correctly, matching the approach already used on line 290.

Suggested change
-	if errors.Cause(err) == context.DeadlineExceeded {
+	if goerrors.Is(err, context.DeadlineExceeded) {
 		if cause := context.Cause(ctx); goerrors.Is(cause, common.ErrWriteTooSlow) {
 			tidblogutil.Logger(ctx).Info("experiencing a wait timeout while writing to TiKV")
 			err = errors.Trace(cause)
 		}
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if errors.Cause(err) == context.DeadlineExceeded {
if cause := context.Cause(ctx); goerrors.Is(cause, common.ErrWriteTooSlow) {
if goerrors.Is(err, context.DeadlineExceeded) {
if cause := context.Cause(ctx); goerrors.Is(cause, common.ErrWriteTooSlow) {
tidblogutil.Logger(ctx).Info("experiencing a wait timeout while writing to TiKV")
err = errors.Trace(cause)
}
}
🤖 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/job_worker.go` around lines 289 - 290, Replace
the direct comparison errors.Cause(err) == context.DeadlineExceeded with a call
to goerrors.Is to consistently detect deadline errors even when wrapped;
specifically, in job_worker.go where the code checks errors.Cause(err) ==
context.DeadlineExceeded (near the block that then inspects context.Cause via
goerrors.Is), change that condition to goerrors.Is(err,
context.DeadlineExceeded) so the deadline check uses the same robust unwrapping
semantics as the subsequent goerrors.Is usage.

@ti-chi-bot

ti-chi-bot Bot commented May 7, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: GMHDBJD, joechenrh

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

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

ti-chi-bot Bot commented May 7, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-05-06 07:59:57.692460152 +0000 UTC m=+254670.565810124: ☑️ agreed by joechenrh.
  • 2026-05-07 11:45:55.704244793 +0000 UTC m=+354628.577594764: ☑️ agreed by GMHDBJD.

@D3Hunter

D3Hunter commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented May 7, 2026

Copy link
Copy Markdown

@D3Hunter: 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:

/retest

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.

@D3Hunter

D3Hunter commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented May 7, 2026

Copy link
Copy Markdown

@D3Hunter: 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:

/retest

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.

@D3Hunter

D3Hunter commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented May 7, 2026

Copy link
Copy Markdown

@D3Hunter: 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:

/retest

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 merged commit a0cdff3 into pingcap:master May 7, 2026
36 checks passed
@ti-chi-bot

ti-chi-bot Bot commented May 7, 2026

Copy link
Copy Markdown

@D3Hunter: 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-lightning-integration-test f4cb5fb link unknown /test pull-lightning-integration-test

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.

@D3Hunter
D3Hunter deleted the codex/lightning-write-timeout-handling-61702 branch May 8, 2026 02:19
@D3Hunter

D3Hunter commented May 8, 2026

Copy link
Copy Markdown
Contributor Author

/cherry-pick release-nextgen-202603

@ti-chi-bot

Copy link
Copy Markdown
Member

@D3Hunter: new pull request created to branch release-nextgen-202603: #68215.

Details

In response to this:

/cherry-pick release-nextgen-202603

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.

takaidohigasi added a commit to takaidohigasi/tidb that referenced this pull request Aug 21, 2026
Resolve conflicts against ~3.5 months of master drift:

- pkg/util/codec, pkg/tablecodec: rebase the DESC-aware encoding onto the
  explicit-collation Encoder introduced by pingcap#69566. EncodeKeyWithDesc
  becomes an Encoder method (with the package-level wrapper kept for
  range/probe-key callers), and GenIndexKey dispatches through the
  caller-supplied encoder on both the ASC fast path and the DESC path.
- pkg/executor: thread indexColDescFlags through the refactored
  buildKeyRanges signature (new rangeMemTracker) and the new unified
  IndexMergeReaderExecutor.buildPartialWorkerKVRanges.
- Resolve files touched only by interim cherry-picks (pingcap#68096, pingcap#68137,
  pingcap#68148, pingcap#68168) to their canonical upstream versions.
- BUILD.bazel: union of dependency edits; adopt upstream shard_count.

Verified with go vet + unit tests on all touched packages, the pkg/ddl
DESC feature tests (-tags=intest), and a full bazel CI build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: takaidohigasi <takaidohigasi@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved lgtm release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants