Skip to content

fix: let analyze_plan run under a caller-provided TaskContext - #8980

Open
LuQQiu wants to merge 2 commits into
lance-format:mainfrom
LuQQiu:lu/analyze-plan-task-context
Open

fix: let analyze_plan run under a caller-provided TaskContext#8980
LuQQiu wants to merge 2 commits into
lance-format:mainfrom
LuQQiu:lu/analyze-plan-task-context

Conversation

@LuQQiu

@LuQQiu LuQQiu commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Problem

analyze_plan executes the plan under a TaskContext derived solely from LanceExecutionOptions. Execution nodes that read a session-config extension at execute time (for example, a distributed routing identity) never see it, so they error inside execute. AnalyzeExec absorbs that per-partition failure and returns an empty, unexecuted plan tree — the analyze output shows the node with metrics=[] and no children, silently hiding the real error rather than surfacing it.

Concretely, a distributed FTS/ANN/scalar-index query executes and returns results normally, but analyze_plan on the same query returns a stub tree with the remote subtree unexecuted (all-zero metrics, no leaf query node).

Fix

Add analyze_plan_with_context(plan, options, task_context), which runs the plan under a caller-supplied TaskContext when Some, falling back to the options-derived context otherwise. analyze_plan keeps its exact signature and behavior (it now delegates with None).

Callers that attach execution-time session-config extensions can then hand the same enriched context to analyze that they use for the real read path, so the analyzed plan executes identically to the query.

Test

Adds a regression test with a node that requires a session-config extension:

  • through the context-less path it reproduces the empty, unexecuted tree (NeedsExtensionExec, metrics=[]);
  • through analyze_plan_with_context with the extension present, it executes and appears in the report.

`analyze_plan` executed the plan under a TaskContext derived solely from
`LanceExecutionOptions`. Nodes that read a session-config extension at
execute time (e.g. distributed routing identity) therefore never saw it,
errored during `execute`, and `AnalyzeExec` absorbed that per-partition
failure into an empty, unexecuted plan tree — the analyze output showed
the node with no metrics and no children, silently hiding the real error.

Add `analyze_plan_with_context`, which runs the plan under a caller-
supplied `TaskContext` when provided (falling back to the options-derived
one otherwise). `analyze_plan` keeps its existing signature and behavior.

Adds a regression test: a node that requires a session-config extension
produces an empty tree via the context-less path and executes correctly
when the extension is supplied through the new entry point.
@github-actions github-actions Bot added the bug Something isn't working label Sep 3, 2026
@LuQQiu

LuQQiu commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

The failed tests are not related to my change

@LuQQiu
LuQQiu marked this pull request as ready for review September 4, 2026 00:11

@lance-gatekeeper lance-gatekeeper Bot 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.

Gate recommendation: request changes.

The helper forwards the caller-provided context as intended, but the regression coverage does not enforce that contract. Make successful child execution observable so removing context forwarding fails the test.

let report = analyze_plan_with_context(plan, options, Some(task_ctx))
.await
.expect("analyze should succeed when the extension is present");
assert!(report.contains("NeedsExtensionExec"));

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.

This assertion only verifies the static plan text; the missing-context report contains the same NeedsExtensionExec node. I temporarily changed the helper to ignore the supplied context and reran cargo test -p lance-datafusion test_analyze_plan_uses_provided_task_context -- --nocapture; the test still passed. Please make execution observable—for example, store an Arc<AtomicBool> in NeedsExtensionExec, set it after the extension check, and assert false after the context-less call and true after the supplied-context call—so this regression test fails if forwarding is removed.

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.

Fixed in 80ba7dfce: the regression now observes successful node execution, and I verified that the test fails when the supplied TaskContext is not forwarded.

@lance-gatekeeper lance-gatekeeper Bot added the K-changes Latest Gatekeeper recommendation requests changes. label Sep 4, 2026
The prior assertion only checked static plan text, which is identical whether
or not the context is forwarded (both reports contain the node). Add an
AtomicBool the node sets only after passing the extension check, and assert it
is false after the context-less call and true after the supplied-context call,
so dropping context forwarding fails the test.
@LuQQiu

LuQQiu commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Good catch — the static-text assertion didn't enforce the contract. Fixed in 80ba7df: NeedsExtensionExec now holds an Arc<AtomicBool> it sets only after the extension check passes in execute. The test asserts the flag is false after the context-less call and true after the supplied-context call. Verified by temporarily making the helper ignore the passed context — the test then fails at "supplied context must be forwarded so the node executes".

@lance-gatekeeper lance-gatekeeper Bot removed the K-changes Latest Gatekeeper recommendation requests changes. label Sep 4, 2026

@lance-gatekeeper lance-gatekeeper Bot 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.

Gate recommendation: approve.

The updated regression now observes successful node execution and fails when the supplied context is not forwarded. This addresses the prior finding; the caller-provided TaskContext path is covered while the existing context-less API remains unchanged.

@lance-gatekeeper lance-gatekeeper Bot added the K-approved Latest Gatekeeper recommendation permits acceptance. label Sep 4, 2026

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

👍 pending CI

let report = analyze_plan_with_context(plan, options, Some(task_ctx))
.await
.expect("analyze should succeed when the extension is present");
assert!(report.contains("NeedsExtensionExec"));

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.

isn't this trivially true?

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

Labels

bug Something isn't working K-approved Latest Gatekeeper recommendation permits acceptance.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants