Skip to content

feat(compression-coordinator): Implement the compression job-submission API for Spider. - #2402

Merged
LinZhihao-723 merged 17 commits into
y-scope:mainfrom
LinZhihao-723:spider-submitter-impl
Jul 21, 2026
Merged

feat(compression-coordinator): Implement the compression job-submission API for Spider.#2402
LinZhihao-723 merged 17 commits into
y-scope:mainfrom
LinZhihao-723:spider-submitter-impl

Conversation

@LinZhihao-723

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

Copy link
Copy Markdown
Member

Description

This PR depends on #2401.

This PR implements S3CompressionJobSubmitter for SpiderClient, filling in the trait added by the preceding scaffolding PR.

Submitting a job

submit_s3_compression_job builds a task graph with one compression task per S3InputSource and a commit task as the graph's termination task, so the commit runs exactly once after every compression task has succeeded. The task inputs (ClpSCompressionOption, the dataset, and the input source) are msgpack-encoded into opaque bytes payloads, matching how the tasks decode them on the Spider side.

Execution policies are applied as given: each compression task receives the policy paired with its input source, and the commit task receives commit_task_execution_policy. The implementation makes no decisions about timeouts, retries, or instance counts — that is the caller's, since only the caller knows how much data a partition holds and how long its jobs typically run.

The TDL package and task-function names are duplicated here as constants rather than imported: the package that defines them depends on this crate, so importing them would form a dependency cycle. They must be kept in sync with the TDL package's definitions, which the constants are annotated to say.

Running a job to completion

run_s3_compression_job_to_completion starts the job idempotently — an "already started" rejection from the cluster is treated as success, so the call is safe whether the job is not-yet-started, running, or already terminal — then polls its state with an exponential backoff bounded by the caller-supplied initial_poll_backoff and max_poll_backoff. The terminal state maps onto CompressionJobOutcome; for a failed job, the cluster's error message is fetched and attached, falling back to a placeholder if that fetch itself fails, so a reporting failure can't mask the underlying job failure.

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.
  • E2e-tested in a dev-branch.

Summary by CodeRabbit

  • New Features
    • Added support for submitting S3 compression jobs with per-input and execution-policy task setup.
    • Added job monitoring with exponential backoff until a terminal outcome is reached.
    • Added consistent outcome handling for succeeded, failed (with available error details), and cancelled jobs.
  • Bug Fixes
    • Improved error reporting across job graph creation, job submission, and input serialization.

The initial and maximum job-state poll backoffs were fixed constants inside the
Spider implementation, so a caller had no way to tune how aggressively a job is
polled. Both are now `Duration` parameters of
`run_s3_compression_job_to_completion`, leaving the pacing decision with the
caller that knows how long its jobs typically run.
@LinZhihao-723
LinZhihao-723 requested a review from a team as a code owner July 20, 2026 13:59
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

Adds the compression-coordinator Rust crate, its error type, and Spider client integration for constructing, submitting, starting, polling, and completing S3 compression jobs.

Changes

Compression coordinator

Layer / File(s) Summary
Coordinator crate setup and errors
components/compression-coordinator/Cargo.toml, components/compression-coordinator/src/error.rs
Registers crate metadata and dependencies, and defines conversions for task graph, serialization, and Spider client failures.
Spider compression task submission
components/compression-coordinator/src/compression_job_submitter/spider.rs
Builds S3 compression task graphs with serialized inputs and termination handling, then submits them through SpiderClient.
Spider job completion monitoring
components/compression-coordinator/src/compression_job_submitter/spider.rs
Starts jobs, polls with capped exponential backoff, and maps terminal Spider states to compression outcomes.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Coordinator
  participant TaskGraph
  participant SpiderClient
  Coordinator->>TaskGraph: build S3 compression graph
  Coordinator->>SpiderClient: submit_job(TaskGraph)
  SpiderClient-->>Coordinator: return JobId
  Coordinator->>SpiderClient: start_job(JobId)
  loop until terminal state
    Coordinator->>SpiderClient: get_job_state(JobId)
    SpiderClient-->>Coordinator: return JobState
  end
  Coordinator->>Coordinator: map terminal state to CompressionJobOutcome
Loading

Possibly related PRs

  • y-scope/clp#2401: Adds submitter APIs and error scaffolding used by this implementation.
  • y-scope/clp#2404: Adds compression task protocol types consumed by task-graph submission.
  • y-scope/clp#2405: Adds handle scaffolding that drives the submitter lifecycle.

Suggested reviewers: bill-hbrhbr

🚥 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 clearly matches the main change: adding Spider-based compression job submission and completion handling for the compression-coordinator crate.
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.

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

🤖 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/compression-coordinator/src/compression_job_submitter/spider.rs`:
- Around line 71-78: Add a nonzero base duration when calculating timeout_ms in
the ExecutionPolicy construction so empty or small input_source.object_keys
batches still have enough time for initialization and network overhead. Preserve
the per-object linear duration while enforcing the minimum timeout before
assigning soft_timeout_ms and hard_timeout_ms.
- Around line 93-104: Align the input descriptor and serialized payload for
input_source in the compression::clp_s_compress task registration and submission
flow. If the worker expects Vec<S3InputSource>, serialize input_source as a
one-element vector; otherwise change the descriptor from Vec<S3InputSource> to
S3InputSource. Preserve the same representation consistently in both the
registered task schema and TaskInput::ValuePayload.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fb1afb68-d0cf-4f10-8c42-83d7c58a8ea2

📥 Commits

Reviewing files that changed from the base of the PR and between e60de7d and 21a51c9.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • Cargo.toml
  • components/clp-rust-utils/src/lib.rs
  • components/clp-rust-utils/src/task_io.rs
  • components/clp-rust-utils/src/task_io/compression.rs
  • components/compression-coordinator/Cargo.toml
  • components/compression-coordinator/src/compression_job_submitter/mod.rs
  • components/compression-coordinator/src/compression_job_submitter/spider.rs
  • components/compression-coordinator/src/error.rs
  • components/compression-coordinator/src/lib.rs

Comment thread components/compression-coordinator/src/compression_job_submitter/spider.rs Outdated

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/compression-coordinator/src/compression_job_submitter/spider.rs (1)

93-94: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Hoist serialization of static task inputs.

clp_s_option and dataset are identical for all compression tasks. Serializing them inside the loop repeatedly allocates and serializes identical byte vectors. Consider serializing them once before the loop and cloning the resulting byte vectors to avoid unnecessary overhead.

♻️ Proposed refactor
+        let clp_s_option_bytes = rmp_serde::to_vec(&clp_s_option)?;
+        let dataset_bytes = rmp_serde::to_vec(&dataset)?;
+
         for (input_source, execution_policy) in input_sources {
             graph.insert_task(TaskDescriptor {
                 // ... task descriptor ...
             })?;
-            inputs.push(TaskInput::ValuePayload(rmp_serde::to_vec(&clp_s_option)?));
-            inputs.push(TaskInput::ValuePayload(rmp_serde::to_vec(&dataset)?));
+            inputs.push(TaskInput::ValuePayload(clp_s_option_bytes.clone()));
+            inputs.push(TaskInput::ValuePayload(dataset_bytes.clone()));
             inputs.push(TaskInput::ValuePayload(rmp_serde::to_vec(&input_source)?));
         }
🤖 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/compression-coordinator/src/compression_job_submitter/spider.rs`
around lines 93 - 94, Hoist serialization of the static clp_s_option and dataset
inputs out of the task-submission loop, storing each resulting byte vector once
before the loop. In the loop, clone and reuse those serialized vectors when
constructing each TaskInput::ValuePayload, while preserving existing error
propagation.
🤖 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.

Outside diff comments:
In `@components/compression-coordinator/src/compression_job_submitter/spider.rs`:
- Around line 93-94: Hoist serialization of the static clp_s_option and dataset
inputs out of the task-submission loop, storing each resulting byte vector once
before the loop. In the loop, clone and reuse those serialized vectors when
constructing each TaskInput::ValuePayload, while preserving existing error
propagation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ff814065-b209-4069-a85a-a2353958050b

📥 Commits

Reviewing files that changed from the base of the PR and between 21a51c9 and 2323707.

📒 Files selected for processing (2)
  • components/compression-coordinator/src/compression_job_submitter/mod.rs
  • components/compression-coordinator/src/compression_job_submitter/spider.rs

# Conflicts:
#	Cargo.lock
#	components/compression-coordinator/Cargo.toml
#	components/compression-coordinator/src/compression_job_submitter/spider.rs
#	components/compression-coordinator/src/error.rs
Comment thread components/compression-coordinator/src/compression_job_submitter/spider.rs Outdated
Comment thread components/compression-coordinator/src/compression_job_submitter/spider.rs Outdated
Co-authored-by: Bingran Hu <bingran.hu@yscope.com>

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/compression-coordinator/src/compression_job_submitter/spider.rs (1)

93-94: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid repeated serialization of loop-invariant data.

The clp_s_option and dataset variables do not change across iterations. Serializing them inside the loop redundantly consumes CPU cycles for every task. You can serialize them once before the loop and clone the resulting Vec<u8> payloads.

♻️ Proposed refactor
        // Pre-serialize outside the loop
        let clp_s_option_payload = rmp_serde::to_vec(&clp_s_option)?;
        let dataset_payload = rmp_serde::to_vec(&dataset)?;

        let mut inputs: Vec<TaskInput> =
            Vec::with_capacity(input_sources.len() * COMPRESSION_TASK_NUM_INPUTS);
        for (input_source, execution_policy) in input_sources {
            // ... (TaskDescriptor insertion) ...

            inputs.push(TaskInput::ValuePayload(clp_s_option_payload.clone()));
            inputs.push(TaskInput::ValuePayload(dataset_payload.clone()));
            inputs.push(TaskInput::ValuePayload(rmp_serde::to_vec(&input_source)?));
        }
🤖 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/compression-coordinator/src/compression_job_submitter/spider.rs`
around lines 93 - 94, Move serialization of the loop-invariant clp_s_option and
dataset values outside the input-building loop, storing their Vec<u8> payloads
once. In the loop that populates inputs, clone those pre-serialized payloads
when creating TaskInput::ValuePayload, while leaving per-input_source
serialization inside the loop.
🤖 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.

Outside diff comments:
In `@components/compression-coordinator/src/compression_job_submitter/spider.rs`:
- Around line 93-94: Move serialization of the loop-invariant clp_s_option and
dataset values outside the input-building loop, storing their Vec<u8> payloads
once. In the loop that populates inputs, clone those pre-serialized payloads
when creating TaskInput::ValuePayload, while leaving per-input_source
serialization inside the loop.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: efdf03ca-484f-4e6b-9e95-434a2bb75e5b

📥 Commits

Reviewing files that changed from the base of the PR and between 2323707 and 9de36fc.

📒 Files selected for processing (1)
  • components/compression-coordinator/src/compression_job_submitter/spider.rs

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/compression-coordinator/src/compression_job_submitter/spider.rs (1)

131-138: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Honour the documented initial poll delay.

get_job_state is called immediately after start_job, so initial_poll_backoff is not used as the delay before the first poll. An initial value greater than max_poll_backoff also bypasses the cap, contrary to the trait contract in components/compression-coordinator/src/compression_job_submitter/mod.rs.

🐛 Proposed fix
-        let mut backoff = initial_poll_backoff;
+        let mut backoff = initial_poll_backoff.min(max_poll_backoff);
         let terminal_state = loop {
+            tokio::time::sleep(backoff).await;
             let state = self.get_job_state(spider_job_id).await?;
             if state.is_terminal() {
                 break state;
             }
-            tokio::time::sleep(backoff).await;
             backoff = (backoff * POLL_BACKOFF_FACTOR).min(max_poll_backoff);
         };
🤖 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/compression-coordinator/src/compression_job_submitter/spider.rs`
around lines 131 - 138, Update the polling loop around get_job_state so it
sleeps for the documented initial poll delay before the first state check, then
applies the existing backoff progression between subsequent polls. Initialize
backoff with initial_poll_backoff capped at max_poll_backoff, preserving the
terminal-state handling and maximum cap for all polls.
🤖 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.

Outside diff comments:
In `@components/compression-coordinator/src/compression_job_submitter/spider.rs`:
- Around line 131-138: Update the polling loop around get_job_state so it sleeps
for the documented initial poll delay before the first state check, then applies
the existing backoff progression between subsequent polls. Initialize backoff
with initial_poll_backoff capped at max_poll_backoff, preserving the
terminal-state handling and maximum cap for all polls.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b8c444f9-6f74-402b-9828-960476124a7e

📥 Commits

Reviewing files that changed from the base of the PR and between 9de36fc and ab89d91.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • components/compression-coordinator/src/compression_job_submitter/spider.rs

Comment thread components/compression-coordinator/src/compression_job_submitter/spider.rs Outdated
Comment thread components/compression-coordinator/src/compression_job_submitter/spider.rs Outdated
Comment thread components/compression-coordinator/src/compression_job_submitter/spider.rs Outdated
LinZhihao-723 and others added 3 commits July 21, 2026 17:00
Co-authored-by: Bingran Hu <bingran.hu@yscope.com>
Bill-hbrhbr
Bill-hbrhbr previously approved these changes Jul 21, 2026
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