Fix: block scheduler while group heads wait - #1612
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe scheduler now coordinates wake-ups through a consumed generation counter and queued completions. It avoids repeated dispatch for blocked groups and exposes dispatch-round counts for validation. ChangesScheduler wake-generation flow
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Worker
participant Scheduler
participant CompletionQueue
participant dispatch_ready
Worker->>Scheduler: report readiness or completion
Scheduler->>CompletionQueue: queue completion
Scheduler->>Scheduler: observe wake generation
Scheduler->>dispatch_ready: dispatch after completion or new generation
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/ut/cpp/hierarchical/test_scheduler.cpp (1)
866-875: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert progress after one group member completes.
The test completes
worker_bimmediately afterworker_a. The aggregate group completion can then wake the scheduler and make this test pass.Keep
worker_brunning afterworker_a.complete(). Assert that the pending single for worker A dispatches while worker B remains busy. This validates the wake-only path for incomplete group-member completion.🤖 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 `@tests/ut/cpp/hierarchical/test_scheduler.cpp` around lines 866 - 875, Update the test around worker_a.complete() so worker_b remains running while waiting for worker_a’s second dispatch; assert worker_a reaches two dispatches and worker_b remains at one before completing worker_b. Move worker_b.complete() after these assertions to validate progress without aggregate group completion.
🤖 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 `@docs/scheduler.md`:
- Around line 40-45: Update the scheduler documentation near the description of
worker completion and wake generations to state that an incomplete group-member
completion advances wake_generation_ and notifies the scheduler without pushing
an entry to the completion FIFO. Keep the existing completion FIFO behavior for
completions that produce a completion event.
---
Nitpick comments:
In `@tests/ut/cpp/hierarchical/test_scheduler.cpp`:
- Around line 866-875: Update the test around worker_a.complete() so worker_b
remains running while waiting for worker_a’s second dispatch; assert worker_a
reaches two dispatches and worker_b remains at one before completing worker_b.
Move worker_b.complete() after these assertions to validate progress without
aggregate group completion.
🪄 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: CHILL
Plan: Pro Plus
Run ID: 20564ba4-a989-454f-9bba-2591b22a7e69
📒 Files selected for processing (6)
docs/scheduler.mdsrc/common/hierarchical/scheduler.cppsrc/common/hierarchical/scheduler.hsrc/common/hierarchical/types.cppsrc/common/hierarchical/types.htests/ut/cpp/hierarchical/test_scheduler.cpp
💤 Files with no reviewable changes (2)
- src/common/hierarchical/types.h
- src/common/hierarchical/types.cpp
56e6181 to
fe02f60
Compare
fe02f60 to
b6eed1b
Compare
ce0679b to
bc1beaf
Compare
|
Reconciled with #1541 (whole-run FIFO admission) and addressed review feedback. Summary: Merge with #1541The branch was rebased onto current
Review items
Testing
The wake-loss audit: all generation bumps and completion pushes happen under |
99b44da to
acfa5d8
Compare
|
Rebased onto current The wake-generation model now sits on top of #1583 staging/activation machinery:
Local: 56 tests x 50 iterations clean; full tests/ut/cpp build clean; clang-format clean. CI re-running on this push. |
Consume each READY or stop notification once instead of treating a non-empty blocked queue as permanent work. Group-member completions that do not enqueue a terminal task completion also advance the wake generation. This keeps queued singles and stop() moving after a member was terminalized early. Tests cover blocked-head sleeping, partial group completion, and the terminalized-member idle transition that previously hung CI.
The edge-triggered wait added with the wake generation drops one producer. A WorkerThread calls on_complete before it stores active_inflight_/inflight_, so the completion wake can reach a parked scheduler while the worker still reads as occupied. The dispatch pass that wake triggers then finds nothing placeable, re-queues through enqueue_ready_cb — which does not notify — and parks again. Nothing posts a further edge, so queued work waits forever: two sub tasks serialized through one worker is the minimal shape, and it hung tests/ut/py/test_worker/test_l4_recursive.py in CI. The old level-triggered predicate re-read queue occupancy and retried until the lane was published, which is what absorbed the window. The completion-before-publication order stays as it is: it keeps a stopping scheduler from reading a worker as no longer busy while its final completion is still unqueued. Add the missing edge instead. WorkerThread takes an on_idle callback, invoked once per finished dispatch after the lane state is published, and Worker::init routes it to Scheduler::notify_ready. Also drop what the deleted predicate orphaned — WorkerManager/WorkerThread needs_activation and stageable_successor_ready, alongside the NextLevelReadyQueues::empty pair already removed — and state the obligation the new model carries in docs/scheduler.md and the scheduler header: any state change that turns queued work into placeable work must push a completion or advance the generation. Advance the generation in start() rather than assigning 1, make the diagnostic round counter relaxed, and take notify_ready out of the group_mu critical section. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
acfa5d8 to
aa183ff
Compare
Summary
Why
A blocked group leaves its queue non-empty, so the previous condition-variable predicate remained permanently true and repeatedly ran dispatch. The stop flag had the same level-triggered behavior while workers were still busy.
Review context
#1565 (comment)
Testing
test_scheduler: 27/27 passed