feat(spur): add burst-buffer staging subsystem with capacity pool and pending reasons#327
Merged
Merged
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #327 +/- ##
==========================================
+ Coverage 66.90% 67.15% +0.25%
==========================================
Files 127 128 +1
Lines 34212 34532 +320
==========================================
+ Hits 22889 23189 +300
- Misses 11323 11343 +20 🚀 New features to boost your workflow:
|
d7300fc to
92bab2e
Compare
92bab2e to
672e53f
Compare
shiv-tyagi
reviewed
Jun 25, 2026
yansun1996
added a commit
to yansun1996/spur
that referenced
this pull request
Jun 25, 2026
…v-tyagi - config.rs: insert blank line between IsolationConfig and BurstBufferConfig doc blocks so rustdoc doesn't merge them into one comment, losing IsolationConfig docs and attaching isolation prose to BurstBufferConfig - limits_cache.rs: rename test to test_proto_to_qos_parses_all_limits (was "five" but covered six fields), add grp_tres round-trip assertion so a regression in opt_tres handling for grp_tres would not pass silently Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
… pending reasons Group 4 of ROCm#307 / closes the scheduler+pool portion of ROCm#309. Model cluster-wide burst-buffer capacity ([burst_buffer] total_gb), parse --bb capacity=NNN, and add a per-job None->Staging->Ready state machine wired into the scheduler. - spur-core: new burst_buffer module (BbStageState, parse_capacity_gb); BurstBufferResources/BurstBufferStageIn reasons + emitters + vocab; bb_stage_state on Job (rides the Raft job snapshot); BurstBufferConfig. - spurctld: derived capacity pool (total - in-use, never drifts from config, mirrors licenses), advance_bb_staging (reserve highest-priority-first), complete_bb_stage_in, drive_bb_stage_in seam; both pending_jobs() drop and tag_blocked_pending_reasons() display gates; precedence is last (Dep->QoS->Resv->Lic->BB) since staging is immediately pre-dispatch. - spurd: --bb capacity= coexists with stage_in/stage_out wrapping. Real agent-side data movement is a follow-up behind drive_bb_stage_in(); the state machine, pool, both reasons, and scheduler hold are complete. Tests: capacity parsing + pool math (spur-core); 4 spurctld integration tests (resource shortage -> BurstBufferResources, mid-stage -> BurstBufferStageIn, dispatch only when Ready); executor wrapping (spurd); REASON_VOCAB extended. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
- Remove the redundant collect-into-pairs-then-strip-priority pattern in advance_bb_staging candidates collection; collect job IDs directly and let the sort closure fetch priority from the already-held write guard. - Drop what-narrating inline comments from the BB gate match arms and scheduler-loop call site; keep only the non-obvious why (double-count guard, drive-before-advance ordering, follow-up seam). Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Reorder scheduler loop: run drive_bb_stage_in()/advance_bb_staging() before tag_blocked_pending_reasons() so BurstBufferStageIn reasons reflect the staging state set in the same cycle, not the previous one. Exclude deadlined jobs from advance_bb_staging() candidates to avoid clobbering PendingReason::DeadLine with BurstBufferStageIn. Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
yansun1996
added a commit
to yansun1996/spur
that referenced
this pull request
Jun 25, 2026
…v-tyagi - config.rs: insert blank line between IsolationConfig and BurstBufferConfig doc blocks so rustdoc doesn't merge them into one comment, losing IsolationConfig docs and attaching isolation prose to BurstBufferConfig - limits_cache.rs: rename test to test_proto_to_qos_parses_all_limits (was "five" but covered six fields), add grp_tres round-trip assertion so a regression in opt_tres handling for grp_tres would not pass silently Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
3afbcd2 to
bc1e464
Compare
…v-tyagi - config.rs: insert blank line between IsolationConfig and BurstBufferConfig doc blocks so rustdoc doesn't merge them into one comment, losing IsolationConfig docs and attaching isolation prose to BurstBufferConfig - limits_cache.rs: rename test to test_proto_to_qos_parses_all_limits (was "five" but covered six fields), add grp_tres round-trip assertion so a regression in opt_tres handling for grp_tres would not pass silently Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
bc1e464 to
a2070e0
Compare
shiv-tyagi
approved these changes
Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft — Group 4 of #307 / the scheduler+pool portion of #309 (burst-buffer staging subsystem).
What
Today
--bbis only script-wrapping in the node agent — no pool, no scheduler awareness, and theBurstBuffer*reasons had no producer. This adds a real subsystem:[burst_buffer] total_gbconfig; free capacity is derived (total − in-use), so it can never drift from config (mirrors how licenses work). A job holds capacity while Running/Suspended/Completing, or Pending-and-staging.--bb capacity=NNNgrammar (GB), parsed by a sharedspur-corehelper; coexists with the agent'sstage_in:/stage_out:directives.None → Staging → Ready(onJob, rides the existing Raft snapshot — no new WAL op). OnlyReady/no-BB jobs dispatch.pending_jobs()(drop) andtag_blocked_pending_reasons()(display) so they can't diverge:BurstBufferResources— capacity shortage.BurstBufferStageIn— capacity reserved, stage-in not yet complete.Dependency → QoS → Reservation → Licenses → BurstBuffer— since staging happens immediately pre-dispatch.Scope boundary
Real agent-side data movement is a documented follow-up behind
drive_bb_stage_in()(the controller-side completion seam, called each scheduler cycle). The pool, both reasons, the staging state machine, and the scheduler hold are complete and tested; only the actual byte-copy round-trip is deferred.Tests
Unit (spur-core): capacity parsing + pool alloc/free math. Integration (spurctld, 4 tests): over-capacity →
BurstBufferResources; mid-stage →BurstBufferStageIn; dispatch only whenReady; capacity release on completion. Executor wrapping (spurd).REASON_VOCABextended.Live validation (Spur node)
PENDING Reason=BurstBufferResources✅None→Staging→Readyand reachedRUNNING✅ (state machine end-to-end)PENDING Reason=BurstBufferResources✅ (derived capacity accounting)Static: build/clippy/fmt clean; spur-core 207, spurctld 143, spurd 97 pass.