Skip to content

feat(huntsman): Add support for accessing task graph outputs in a commit task. - #390

Merged
LinZhihao-723 merged 7 commits into
y-scope:mainfrom
LinZhihao-723:commit-outputs
Jul 13, 2026
Merged

feat(huntsman): Add support for accessing task graph outputs in a commit task.#390
LinZhihao-723 merged 7 commits into
y-scope:mainfrom
LinZhihao-723:commit-outputs

Conversation

@LinZhihao-723

@LinZhihao-723 LinZhihao-723 commented Jul 12, 2026

Copy link
Copy Markdown
Member

Description

This PR lets a commit task read the outputs of its job's task graph from its TaskContext, mirroring the job-level output-retrieval APIs but delivering the data inline to the commit task instead of to an external client. The execution context that storage ships to the execution manager already carries a serialized payload per task instance; this PR generalizes that payload so it carries task inputs for regular tasks (unchanged behavior) and the task-graph outputs for a commit task, then routes it into the commit task's TaskContext where a new accessor deserializes it on demand. The wire field is renamed once to reflect the dual role, and the rename preserves the protobuf tag so it stays wire-compatible.

Wire payload: one field for inputs and outputs (spider-core, spider-proto)

  • Renames ExecutionContext::serialized_inputs to serialized_task_io in the core type (spider-core/src/types/io.rs) and in the protobuf message (spider-proto/storage/storage.proto, regenerated spider-proto-rust/src/generated/storage.rs, and the TryFrom conversion in spider-proto-rust/src/io.rs). The protobuf field keeps tag 4, so the change is wire-compatible.
  • The field now means "task inputs for a regular task, task-graph outputs for a commit task"; the producer (storage) decides which based on the task kind.

Storage: build the commit task's execution context from task-graph outputs (spider-storage)

  • Adds TaskGraph::read_output_payloads() (cache/task.rs), which reads the payloads of every task-graph output, and collapses the three previously-duplicated read loops (get_outputs, the succeed_task_instance completion path, and create_commit_task_instance) onto it.
  • create_commit_task_instance (cache/job.rs) now serializes the task-graph outputs via SerializedTaskOutputs::serialize_with_size_hint and stores the raw bytes in the execution context's serialized_task_io. Regular-task registration continues to place the task inputs there, and the cleanup path leaves it empty.
  • Adds InternalError::TaskOutputs(#[from] spider_core::types::io::TaskOutputsError) (cache/error.rs) so the output serialization error propagates through the cache error type.

Execution manager: route the payload into the TaskContext (spider-execution-manager)

  • build_request (process_pool.rs) inspects the task kind: for a commit task it moves serialized_task_io into the TaskContext's task-graph outputs and leaves the executor's raw_inputs empty; for any other task it passes serialized_task_io through as raw_inputs and leaves the context without task-graph outputs.
  • Adds InternalError::BuildTaskContext(#[from] spider_tdl::TdlError) so a failed TaskContext construction surfaces as a pool error.

Executor API: TaskContext (spider-tdl)

  • TaskContext gains a private serialized_task_graph_outputs: Option<Vec<u8>> field holding the raw serialized outputs (kept raw so they pass through the execution manager to the executor without an intermediate deserialize/re-encode).
  • TaskContext::new is now fallible (Result<Self, TdlError>) and validates the invariant that task-graph outputs are present for a commit task and absent otherwise, returning TdlError::InvalidTaskContext on a violation.
  • get_task_graph_outputs(&self) -> Result<Option<Vec<TaskOutput>>, TdlError> deserializes the raw bytes on demand: Ok(Some(..)) for a commit task, Ok(None) for a non-commit task, and a deserialization error if the stored bytes are corrupt.
  • Adds the TdlError::InvalidTaskContext(String) variant (error.rs). Call sites that construct a TaskContext (the #[task] handler test helpers and integration harnesses) are updated for the fallible constructor.

Tests

  • Storage (spider-storage/tests/scheduling_infra.rs): the mock execution manager's commit handler now decodes the commit context's serialized_task_io as SerializedTaskOutputs and asserts the decode succeeds, so every commit-bearing workload (test_flat_success and its variants) exercises the new payload end-to-end.
  • Execution manager (spider-execution-manager/src/process_pool.rs): unit tests for build_request covering the commit routing (populated and empty outputs) and the regular-task pass-through.
  • Executor unit (spider-tdl/src/task_context.rs, error.rs): construction-invariant tests (new rejects outputs on a non-commit task and missing outputs on a commit task), accessor tests (populated, empty, non-commit None, corrupt bytes, msgpack round-trip), and the error round-trip covers the new variant.
  • Executor end-to-end (integration-test-tasks, test-utils, task-executor tests): adds a commit task assert_outputs_sum_zero that reads its task-graph outputs and asserts the i64 values sum to zero; adds build_commit_ctx / commit_execute_request harness helpers to construct a commit context carrying serialized outputs; and adds four test_executor.rs cases (sums to zero, doesn't sum to zero, empty outputs, and a non-commit context) exercised against a real spider-task-executor subprocess.

Notes

  • The raw serialized outputs are carried verbatim from storage through the execution manager into the TaskContext and are only deserialized when the commit task calls get_task_graph_outputs, so the execution manager never pays for a deserialize/re-encode of a payload it only forwards.
  • The commit-vs-outputs invariant is enforced once, at TaskContext::new; get_task_graph_outputs trusts it and returns None purely from the absence of stored bytes rather than re-checking the task id.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

  • Ensure all workflows pass.
  • Ensure new test cases all pass.

Summary by CodeRabbit

  • New Features

    • Commit tasks can now receive and process serialized task-graph outputs.
    • Added validation for task contexts to ensure outputs are supplied only for commit tasks.
    • Added support for reading stored task outputs and reporting unavailable outputs clearly.
    • Added a task for verifying that committed output values sum to zero.
  • Bug Fixes

    • Improved routing of task inputs and outputs during task execution.
    • Added clearer errors for invalid task contexts and output-processing failures.
    • Updated execution-context payload naming from serialized_inputs to serialized_task_io.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@LinZhihao-723, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 56 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a44db84d-1df2-4360-a2c9-008d416d173d

📥 Commits

Reviewing files that changed from the base of the PR and between b2da5da and 98da0b7.

📒 Files selected for processing (1)
  • components/spider-tdl/src/error.rs

Walkthrough

This change renames serialized task I/O fields, adds validated task-graph output handling to TaskContext, routes commit outputs through execution requests, updates storage serialization, and adds integration coverage for commit-task output validation.

Changes

Task output flow

Layer / File(s) Summary
Execution context field migration
components/spider-core/..., components/spider-proto/..., components/spider-storage/..., tests/huntsman/...
Renames serialized_inputs to serialized_task_io across Rust types, protobuf conversion, storage responses, and test request builders.
Task context output contract
components/spider-tdl/..., tests/huntsman/tdl-integration/...
Adds serialized task-graph outputs, validates their presence for commit tasks, deserializes them, and introduces InvalidTaskContext error handling.
Storage output collection and commit context
components/spider-storage/src/cache/..., components/spider-storage/tests/...
Adds bulk output reading, serializes commit outputs into execution contexts, and validates decoded outputs during scheduling tests.
Executor request routing
components/spider-execution-manager/...
Routes commit outputs into TaskContext, keeps non-commit inputs in raw_inputs, propagates construction errors, and tests both paths.
Commit task integration coverage
tests/huntsman/integration-test-tasks/..., tests/huntsman/task-executor/..., tests/huntsman/test-utils/...
Adds a commit task that checks output sums and end-to-end tests for successful, empty, non-zero, and non-commit execution cases.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TaskGraph
  participant SharedJobControlBlock
  participant ProcessPool
  participant TaskContext
  participant Executor
  TaskGraph->>SharedJobControlBlock: read output payloads
  SharedJobControlBlock->>TaskContext: serialize outputs for commit context
  ProcessPool->>TaskContext: construct validated TaskContext
  ProcessPool->>Executor: send commit context with empty raw_inputs
  Executor->>TaskContext: decode task-graph outputs
Loading

Possibly related PRs

  • y-scope/spider#326: Updates the same process-pool request construction and task-context serialization path.
  • y-scope/spider#329: Introduces the runtime ExecutionContext payload updated by this rename.
  • y-scope/spider#343: Refactors the serialized execution-context input payload that this change renames and routes.

Suggested reviewers: sitaowang1998

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: commit tasks gaining access to task graph outputs.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ 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.

@LinZhihao-723
LinZhihao-723 marked this pull request as ready for review July 13, 2026 01:22
@LinZhihao-723
LinZhihao-723 requested review from a team and sitaowang1998 as code owners July 13, 2026 01:22
@LinZhihao-723 LinZhihao-723 changed the title [WIP] feat(huntsman): Add support for accessing task graph outputs in a commit task. feat(huntsman): Add support for accessing task graph outputs in a commit task. Jul 13, 2026
@sitaowang1998

Copy link
Copy Markdown
Collaborator

Before I go into details, I have a question: should we reuse TaskContext and make it hold different things for different kinds of tasks or should we just create another struct for it?

@LinZhihao-723

Copy link
Copy Markdown
Member Author

Before I go into details, I have a question: should we reuse TaskContext and make it hold different things for different kinds of tasks or should we just create another struct for it?

I think we should use a single type for it, even the underlying data it holds differ depending on the task types. This makes the user-side more friendly since you don't need to decide what the type of the first parameter for a task function is.

/// Returns an error if:
///
/// * Forwards [`SerializedTaskOutputs::deserialize_from_raw`]'s return values on failure.
pub fn get_task_graph_outputs(&self) -> Result<Option<Vec<TaskOutput>>, TdlError> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe we should return an error instead of None if called by non-commit task?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's actually my initial implementation in f6b2227. But I think from a general perspective, get_task_graph_outputs is more like a method to query the task graph outputs; it doesn't necessarily need to fail if the outputs are not ready. This should give us more flexibility to reuse this method, for example, in cleanup tasks.

sitaowang1998
sitaowang1998 previously approved these changes Jul 13, 2026

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
components/spider-tdl/src/task_context.rs (1)

24-77: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy lift

Enforce the TaskContext invariant during deserialization

TaskContext::new enforces “outputs present iff commit task”, but #[derive(serde::Deserialize)] bypasses that check, so rmp_serde::from_slice can still materialise an invalid TaskContext across the executor boundary. Consider deserialising through a validated wrapper (#[serde(try_from = "...")] or a custom Deserialize impl) so the same invariant is applied on decode, not just at construction time.

🤖 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 `@components/spider-tdl/src/task_context.rs` around lines 24 - 77, Ensure
TaskContext deserialization enforces the same “serialized_task_graph_outputs is
present only for TaskId::Commit” invariant as TaskContext::new. Replace the
derived deserialization path with a validated conversion or custom Deserialize
implementation that routes decoded fields through TaskContext::new and
propagates validation errors.
🤖 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 `@components/spider-tdl/src/error.rs`:
- Around line 23-25: Update the Display error text for InvalidTaskContext to
describe an invalid task context and preserve the underlying validation detail,
rather than labelling it as an internal error. Leave the other error variants
unchanged.

---

Nitpick comments:
In `@components/spider-tdl/src/task_context.rs`:
- Around line 24-77: Ensure TaskContext deserialization enforces the same
“serialized_task_graph_outputs is present only for TaskId::Commit” invariant as
TaskContext::new. Replace the derived deserialization path with a validated
conversion or custom Deserialize implementation that routes decoded fields
through TaskContext::new and propagates validation errors.
🪄 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: 84428d9f-ac80-4879-8dbc-36a5df09d7ae

📥 Commits

Reviewing files that changed from the base of the PR and between 1bbb996 and b2da5da.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • components/spider-proto-rust/src/generated/storage.rs is excluded by !**/generated/**
📒 Files selected for processing (21)
  • components/spider-core/src/types/io.rs
  • components/spider-execution-manager/Cargo.toml
  • components/spider-execution-manager/src/process_pool.rs
  • components/spider-proto-rust/src/io.rs
  • components/spider-proto/storage/storage.proto
  • components/spider-storage/src/cache/error.rs
  • components/spider-storage/src/cache/job.rs
  • components/spider-storage/src/cache/task.rs
  • components/spider-storage/src/grpc.rs
  • components/spider-storage/tests/scheduling_infra.rs
  • components/spider-tdl/src/error.rs
  • components/spider-tdl/src/task.rs
  • components/spider-tdl/src/task_context.rs
  • components/spider-tdl/tests/test_task_macro.rs
  • tests/huntsman/em-runtime/tests/test_runtime.rs
  • tests/huntsman/integration-test-tasks/Cargo.toml
  • tests/huntsman/integration-test-tasks/src/lib.rs
  • tests/huntsman/task-executor/tests/test_executor.rs
  • tests/huntsman/task-executor/tests/test_process_pool.rs
  • tests/huntsman/tdl-integration/tests/complex.rs
  • tests/huntsman/test-utils/src/executor.rs

Comment thread components/spider-tdl/src/error.rs Outdated
@LinZhihao-723
LinZhihao-723 merged commit aa9072f into y-scope:main Jul 13, 2026
15 checks passed
@LinZhihao-723
LinZhihao-723 deleted the commit-outputs branch July 13, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants