Skip to content

feat(spider-scheduler): Reschedule task assignments returned by lost execution managers. - #395

Merged
LinZhihao-723 merged 4 commits into
y-scope:mainfrom
LinZhihao-723:reschedule-queue-wiring
Jul 14, 2026
Merged

feat(spider-scheduler): Reschedule task assignments returned by lost execution managers.#395
LinZhihao-723 merged 4 commits into
y-scope:mainfrom
LinZhihao-723:reschedule-queue-wiring

Conversation

@LinZhihao-723

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

Copy link
Copy Markdown
Member

Description

When an execution manager is lost, the execution-manager registry already pushes that manager's outstanding task assignments onto the scheduler's reschedule queue, but nothing consumed that queue: its reader was parked, unused, on the Runtime. This PR wires the reschedule queue's reader into the scheduler core and implements reschedule ingestion in the round-robin core, so a lost manager's assignments are re-placed and re-dispatched instead of being silently dropped.

The enabling change is that the storage session is moved onto each TaskAssignment. A rescheduled assignment travels the reschedule queue as a bare TaskAssignment, with no session paired alongside it, so it could not otherwise be checked against the scheduler's current session. Carrying session_id on the assignment makes it self-describing, which both lets the core drop assignments from a superseded session and collapses the several places that previously tracked the session next to the assignment down to a single source of truth.

Wire the reschedule queue reader into the scheduler core (core.rs, runtime.rs)

  • SchedulerCore::run gains a reschedule_queue_reader: tokio::sync::mpsc::UnboundedReceiver<TaskAssignment> parameter, threaded through RoundRobinCore into RoundRobin.
  • create_runtime now hands the reschedule queue's receiver to the spawned core instead of parking it on Runtime. The execution-manager registry continues to hold the sender and pushes a dead manager's outstanding assignments onto it.

Carry the storage session on each TaskAssignment (spider-core, dispatch queue, proto, execution manager)

  • Added session_id: SessionId to TaskAssignment (the scheduler's view of storage's session when the assignment was produced), and removed the now-redundant SchedulerResponse::session_id so the assignment is the single source of truth.
  • DispatchQueueSource::dequeue now returns a bare TaskAssignment instead of a (SessionId, TaskAssignment) pair; SchedulerServiceState::next_task and make_next_task_response follow suit. The dispatch-queue reader keeps its session read-guard, so the queue's drain-and-invalidate behavior on bump_session_id is unchanged.
  • The wire protocol is unchanged: SchedulerAssignment already carries session_id, so only the spider-proto-rust conversion changes to route it into task_assignment.session_id. The execution manager now reads response.task_assignment.session_id.

Reschedule ingestion in the round-robin core (implementation.rs)

  • tick() now runs a new reschedule() step after consuming the inbound poll and before making scheduling decisions, so rescheduled tasks are filtered against the up-to-date session and dispatched in the same tick.
  • reschedule() drains a bounded snapshot of the reschedule queue (assignments pushed concurrently by the registry during the drain are deferred to the next tick rather than extending the loop), drops any assignment from a superseded session (session_id < storage_session_id), groups the survivors by task kind, and loads them through the same commit-ready / cleanup-ready / ready enqueue helpers as the inbound path — so finalizing semantics and buffered-task de-duplication apply identically. Re-dispatched assignments receive a fresh id and the current session.
  • Every assignment the core enqueues is now stamped with the current storage_session_id.

Tests (round_robin/tests.rs)

  • White-box tick()-driven tests: a rescheduled ready task is re-dispatched with the current session and a fresh id; a stale-session assignment is dropped; and a rescheduled task is de-duplicated against a concurrently-buffered inbound copy of the same task.
  • A black-box property test drives the public run() loop, randomly pushes a subset of dispatched assignments back onto the reschedule queue (each task at most once, using a real rand source), and asserts that every task eventually completes and that each rescheduled task is dispatched exactly twice.
  • Added rand as a dev-dependency of spider-scheduler.

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 both white-box testing and black-box testing pass to assert the expected rescheduling behavior.

Summary by CodeRabbit

  • New Features

    • Added support for re-queuing task assignments after an execution manager is lost, including automatic redispatch with session validation and correct finalization ordering.
  • Improvements

    • Session information is now carried directly on each task assignment, improving consistency across scheduling, execution, and task APIs.
    • Enhanced resilience with stronger handling of stale sessions, deduplication of recovered work, and broader recovery under load.
  • Bug Fixes

    • Fixed session handling so stale assignments are dropped reliably and liveness refreshes use the pinned session from the assignment.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

TaskAssignment now owns the storage session ID. Scheduler APIs and gRPC conversion use this nested value, while RoundRobin accepts a reschedule queue, filters and re-injects assignments, and emits session-tagged dispatches with expanded test coverage.

Changes

Scheduler assignment rescheduling

Layer / File(s) Summary
Session identity contract
components/spider-core/src/types/scheduler.rs, components/spider-proto-rust/src/assignment.rs, components/spider-execution-manager/src/runtime.rs, tests/huntsman/em-runtime/tests/test_runtime.rs
Session identity moved from SchedulerResponse to TaskAssignment, and execution-manager session handling now reads the nested field.
Scheduler API and queue contracts
components/spider-scheduler/src/core.rs, components/spider-scheduler/src/dispatch_queue.rs, components/spider-scheduler/src/service.rs, components/spider-scheduler/src/grpc.rs
Scheduler core, queue, service, and gRPC interfaces now pass TaskAssignment directly with its embedded session ID.
Round-robin rescheduling flow
components/spider-scheduler/src/core_impl/round_robin/implementation.rs
RoundRobin consumes rescheduled assignments during ticks, filters older sessions, partitions entries by task type, and emits session-tagged assignments.
Rescheduling validation and support
components/spider-scheduler/src/core_impl/round_robin/tests.rs, components/spider-scheduler/src/execution_manager_registry.rs, components/spider-scheduler/Cargo.toml
Tests cover redispatch, stale-session removal, deduplication, and randomized rescheduling behaviour; test assignment construction includes session IDs.

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

Sequence Diagram(s)

sequenceDiagram
  participant ExecutionManager
  participant RescheduleQueue
  participant RoundRobin
  participant DispatchQueue
  ExecutionManager->>RescheduleQueue: return TaskAssignment
  RescheduleQueue->>RoundRobin: provide assignment on tick
  RoundRobin->>RoundRobin: filter session and classify task
  RoundRobin->>DispatchQueue: enqueue assignment for dispatch
Loading

Possibly related PRs

  • y-scope/spider#348: Both modify RoundRobin assignment construction and scheduler-core wiring.
  • y-scope/spider#350: Both modify execution-manager handling of scheduler response session information.
  • y-scope/spider#369: Both modify scheduler gRPC next_task session-ID mapping.

Suggested reviewers: sitaowang1998

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: rescheduling task assignments from lost execution managers.
✨ 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 20:21
@LinZhihao-723
LinZhihao-723 requested review from a team and sitaowang1998 as code owners July 13, 2026 20:21

@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 (2)
components/spider-scheduler/src/core_impl/round_robin/implementation.rs (2)

540-542: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider logging dropped stale-session assignments.

Stale rescheduled assignments are discarded silently here, whereas comparable ignore paths (e.g. enqueue_ready_entries for finalizing jobs) emit a trace. Since rescheduling is a lost-EM recovery path, a debug/trace line recording the dropped job_id/task_id and both session IDs would aid incident diagnosis without changing behaviour.

🤖 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-scheduler/src/core_impl/round_robin/implementation.rs`
around lines 540 - 542, Add a debug or trace log before the continue in the
stale-assignment branch, recording the dropped assignment’s job_id, task_id,
assignment.session_id, and self.storage_session_id. Preserve the existing
discard behavior and follow the logging style used by enqueue_ready_entries.

207-207: 🩺 Stability & Availability | 🔵 Trivial

Unbounded reschedule queue: consider backpressure/monitoring. The reschedule() snapshot bounds per-tick work, but the channel itself is unbounded, so sustained EM loss (or a redispatch path that keeps re-queuing) can grow this queue without limit and pressure scheduler memory. Consider emitting a gauge/metric for the queue depth and/or an alert threshold so operators can detect a runaway reschedule backlog before it degrades the scheduler.

🤖 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-scheduler/src/core_impl/round_robin/implementation.rs` at
line 207, Instrument the unbounded reschedule queue represented by
reschedule_queue_reader with a queue-depth gauge, updating it whenever items are
enqueued or drained; add an alert or threshold for sustained excessive depth so
operators can detect runaway backlog. Preserve the existing per-tick
reschedule() work bound and scheduling behavior.
🤖 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-scheduler/Cargo.toml`:
- Line 34: Update the rand dependency declaration in Cargo.toml from 0.9.1 to
version 0.9.3 or later, ensuring the resolved dependency is outside the advisory
range.

---

Nitpick comments:
In `@components/spider-scheduler/src/core_impl/round_robin/implementation.rs`:
- Around line 540-542: Add a debug or trace log before the continue in the
stale-assignment branch, recording the dropped assignment’s job_id, task_id,
assignment.session_id, and self.storage_session_id. Preserve the existing
discard behavior and follow the logging style used by enqueue_ready_entries.
- Line 207: Instrument the unbounded reschedule queue represented by
reschedule_queue_reader with a queue-depth gauge, updating it whenever items are
enqueued or drained; add an alert or threshold for sustained excessive depth so
operators can detect runaway backlog. Preserve the existing per-tick
reschedule() work bound and scheduling behavior.
🪄 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: 99e834d3-c561-43d4-a47d-b55a06fd12a3

📥 Commits

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

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (13)
  • components/spider-core/src/types/scheduler.rs
  • components/spider-execution-manager/src/runtime.rs
  • components/spider-proto-rust/src/assignment.rs
  • components/spider-scheduler/Cargo.toml
  • components/spider-scheduler/src/core.rs
  • components/spider-scheduler/src/core_impl/round_robin/implementation.rs
  • components/spider-scheduler/src/core_impl/round_robin/tests.rs
  • components/spider-scheduler/src/dispatch_queue.rs
  • components/spider-scheduler/src/execution_manager_registry.rs
  • components/spider-scheduler/src/grpc.rs
  • components/spider-scheduler/src/runtime.rs
  • components/spider-scheduler/src/service.rs
  • tests/huntsman/em-runtime/tests/test_runtime.rs

[dev-dependencies]
anyhow = "1.0.102"
dashmap = "6.1.0"
rand = "0.9.1"

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.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if rand 0.9.1 exists on crates.io
curl -s https://crates.io/api/v1/crates/rand/0.9.1 | jq '.version.num, .version.yanked'

# Check for security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: RUST, package: "rand") {
    nodes {
      advisory { summary severity publishedAt }
      vulnerableVersionRange
      firstPatchedVersion { identifier }
    }
  }
}'

Repository: y-scope/spider

Length of output: 880


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Raw crates.io response for rand 0.9.1:"
curl -s https://crates.io/api/v1/crates/rand/0.9.1 | jq .

echo
echo "Searching published rand versions for 0.9.1:"
curl -s "https://crates.io/api/v1/crates/rand" | jq -r '.versions[].num' | grep -x '0.9.1' || true

Repository: y-scope/spider

Length of output: 599


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Trying crates.io sparse index entry for rand:"
curl -s https://index.crates.io/ra/nd/rand | sed -n '1,120p'

Repository: y-scope/spider

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -euo pipefail

curl -s https://index.crates.io/ra/nd/rand | grep -m1 '"vers":"0.9.1"' || true

Repository: y-scope/spider

Length of output: 1542


Bump rand to 0.9.3 or later rand 0.9.1 is published, but it falls in the advisory range >= 0.9.0, < 0.9.3. components/spider-scheduler/Cargo.toml:34

🤖 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-scheduler/Cargo.toml` at line 34, Update the rand
dependency declaration in Cargo.toml from 0.9.1 to version 0.9.3 or later,
ensuring the resolved dependency is outside the advisory range.

@LinZhihao-723
LinZhihao-723 merged commit 1fe99d6 into y-scope:main Jul 14, 2026
17 checks passed
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