Skip to content

fix: preserve primary error across join map cancellation - #27614

Merged
XuPeng-SH merged 11 commits into
matrixorigin:mainfrom
jiangxinmeng1:fix/issue-27524-fk-error-propagation
Aug 28, 2026
Merged

fix: preserve primary error across join map cancellation#27614
XuPeng-SH merged 11 commits into
matrixorigin:mainfrom
jiangxinmeng1:fix/issue-27524-fk-error-propagation

Conversation

@jiangxinmeng1

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

issue #27524

What this PR does / why we need it:

  • Preserve the primary execution error when a JoinMap consumer is canceled by a sibling pipeline.
  • Return the cancellation cause instead of the generic context canceled error.
  • Add regression coverage for foreign-key errors propagated through cancellation.

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@XuPeng-SH XuPeng-SH 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.

Two blocking correctness issues remain on this exact head.

  1. pkg/vm/message/joinMapMsg.go:663 unconditionally returns context.Cause(ctx). This bypasses the query-cancellation classification in normalizeScopeRunError. A reachable query context created with context.WithTimeoutCause has Err() == DeadlineExceeded but Cause() == its diagnostic MO error. With a real operator blocked in ReceiveJoinMap until that deadline, this head returns only "internal error: internal executor exec"; DeadlineExceeded is absent. The identical end-to-end test passes on base a5877b6. The existing compile contract explicitly preserves DeadlineExceeded so callers can classify timeout first and attach the diagnostic cause afterward. Keep query deadlines as DeadlineExceeded; only promote the pipeline-local sibling cause after distinguishing query cancellation.

  2. The patch only fixes the ctxDone winner and therefore does not close issue #27524. MessageReceiver checks queued messages before ctx.Done(). If a canceled HashBuild first publishes NewJoinMapBuildErrorResult(context.Canceled), ReceiveJoinMap consumes that terminal message and returns "internal error: context canceled" without entering the changed branch, even when the pipeline cancel cause is the FK violation. I reproduced this deterministically by queueing the canceled BuildError under a context canceled with NewErrFKNoReferencedRow2. The expected FK error is not in the returned chain. This ordering is reachable through HashBuild.finalizeBuildFailure -> publishBuildError, and the issue log at joinMapDependency.go:57 shows that exact context-canceled snapshot path.

Please handle cancellation precedence at the common producer/aggregation boundary for both message-first and ctx-first orderings, while preserving query deadline classification. Add deterministic tests for both interleavings plus the timeout control, and public multi-CN/Proxy regression evidence for the SQL-visible FK error contract.

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

Reviewed exact head 378294be52619a1c8d90f2d129414a0e929b5d24 against base a5877b6126c949e6c9f9e71a899d08e229cf7476. Two concrete error-precedence paths remain incorrect.

  1. The new ctx-done branch unconditionally returns context.Cause(ctx). For context.WithTimeoutCause, ctx.Err() is DeadlineExceeded while the cause is diagnostic detail. Returning the cause here bypasses normalizeScopeRunError, whose explicit contract preserves DeadlineExceeded so callers can classify query timeout. A join-map consumer blocked until a query deadline now returns only the diagnostic MO error. Preserve deadline classification and promote a pipeline-local sibling cause only after distinguishing query cancellation.

  2. MessageReceiver.ReceiveMessage checks queued messages before ctx.Done(). If canceled HashBuild publishes NewJoinMapBuildErrorResult(context.Canceled) first, ReceiveJoinMapResult returns that terminal result and never executes the changed ctx-done branch; ReceiveJoinMap then returns generic context-canceled even when the pipeline cancellation cause is the FK violation. This is the producer/message-first interleaving from the issue path.

Resolve context-shaped dependency failures against the pipeline cause at a boundary shared by both orderings, without replacing independent operator errors or query deadlines. Add deterministic ctx-first and message-first tests plus a WithTimeoutCause control; the current test covers only ctx-first cancellation.

@matrix-meow matrix-meow added size/M Denotes a PR that changes [100,499] lines and removed size/S Denotes a PR that changes [10,99] lines labels Aug 27, 2026

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

Deep re-review of exact head ed5ed4d. The restored unit matrix closes the prior white-box coverage gap and passes under repeated race testing, but the distributed regression still does not exercise the reported cancellation race. Requesting changes for the inline blocker.

Comment thread test/distributed/cases/prepare/issue_27524_fk_insert_select.sql Outdated

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

Deep re-review of exact head 0404ace, including the full review/thread history and the increment since ed5ed4d. The distributed regression now restores the issue's late-failure shape: 10,000 rows, only the final FK missing, five consecutive attempts with FK-specific errors and zero-row atomicity checks, followed by a successful valid FK insert on the same connection. This closes my prior blocker. The complete production diff remains coherent across ctx-first/message-first cancellation, joined causes, QueryInterrupted, query deadlines, and independent producer deadlines. Validation passed: affected package list/build/vet/tests for message, hashbuild, hashjoin, and compile; 20 race repetitions of the cancellation/deadline/concurrent message matrix; diff check; and the exact-head multi-CN Proxy BVT check is green.

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

Reviewed exact head 0404acef886339ae603ba410fdccab3e32e67eb9. The cancellation precedence is now applied at the shared JoinMap receive boundary, so context-first and queued-message-first outcomes agree without mutating the immutable broadcast result. Substantive sibling causes survive cancellation-shaped fallout, while query and independent producer deadlines remain classifiable as DeadlineExceeded; joined and QueryInterrupted forms are covered. The concurrent-consumer test closes the publication/waiter lifecycle, and the repeated 10,000-row late-FK BVT verifies the SQL-visible error, atomic rollback, and same-connection recovery. Exact-head CI is green; no blocking correctness, lifecycle, or boundedness finding remains.

@XuPeng-SH XuPeng-SH 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.

Reviewed exact head 0404ace. The change preserves the primary join-map failure while using cancellation errors only as fallback; success, cancellation, concurrent error reporting, and cleanup paths remain coherent. CI is green. No blocking correctness, liveness, resource-lifecycle, compatibility, or performance issue found.

@mergify

mergify Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-08-28 09:05 UTC · Rule: main · triggered by rule Automatic queue on approval for main
  • 🟠 Checks running · in-place
  • 🚫 Left the queue2026-08-28 09:31 UTC · at 53af8c26ef2c8b18c4993764bfd0a7ccbce64a62

This pull request spent 26 minutes 19 seconds in the queue, with no time running CI.

Waiting for
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone CI / SCA Test on Linux/arm64
    • check-skipped = Matrixone CI / SCA Test on Linux/arm64
    • check-success = Matrixone CI / SCA Test on Linux/arm64
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage
    • check-success = Matrixone Utils CI / Coverage
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-skipped = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-success = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-success = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
All conditions
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone CI / SCA Test on Linux/arm64
    • check-skipped = Matrixone CI / SCA Test on Linux/arm64
    • check-success = Matrixone CI / SCA Test on Linux/arm64
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage
    • check-success = Matrixone Utils CI / Coverage
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-skipped = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-success = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-success = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-approved [🛡 GitHub branch protection]

Reason

Pull request #27614 has been dequeued

Pull request from fork cannot be queued. This pull request comes from a fork, and Mergify needs the author's permission to update its branch.

The author needs to enable "Allow edits from maintainers" on this pull request.

Failing checks:

Hint

You should look at the reason for the failure and decide if the pull request needs to be fixed or if you want to requeue it.
If you do update this pull request, it will automatically be requeued once the queue conditions match again.
If you think this was a flaky issue instead, you can requeue the pull request, without updating it, by posting a @mergifyio queue comment.

Tick the box to put this pull request back in the merge queue (same as @mergifyio queue).

  • Requeue this pull request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dequeued kind/bug Something isn't working size/M Denotes a PR that changes [100,499] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants