slurm: make job-status retries resilient to real transient failure#973
Conversation
The transient-error check is duplicated across is_job_running, is_job_completed, and get_job_status, and the copies have started to drift. Fold all three retry sites onto one helper. No behavior change. Signed-off-by: Ilya Yanok <iyanok@nvidia.com>
The retry loop re-runs sacct immediately, so fast-failing transients (e.g. connection refused while slurmctld/slurmdbd restarts) exhaust retry_threshold in under a second — the retry only survives failures shorter than one sacct invocation, and a single hiccup kills a multi-hour scenario. Pause between attempts (status_retry_pause_seconds, default 10 s, the order of slurm's own message timeout): three attempts now span ~30 s, within the default monitor_interval cadence. The sleep only runs after a failed attempt; the test fixture pins it to 0. Signed-off-by: Ilya Yanok <iyanok@nvidia.com>
Sites wrapping the slurm CLIs (proxies, shims for split login nodes) emit their own transient transport errors, which today bypass the retry entirely and kill the scenario on first occurrence. Let the system config extend the retryable set via extra_transient_status_errors. Signed-off-by: Ilya Yanok <iyanok@nvidia.com>
📝 WalkthroughWalkthroughSlurm status queries now support configurable transient-error patterns and retry pauses. Shared detection is used by running, completed, and status queries, with validation and tests for configured patterns and retry behavior. ChangesSlurm status retry behavior
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@src/cloudai/systems/slurm/slurm_system.py`:
- Around line 273-279: Update the retry handling in the status-query branches
around _is_transient_status_error and the corresponding branches near the other
retry sites so time.sleep(self.status_retry_pause_seconds) runs only when
retry_count is still below retry_threshold. Apply this guard consistently to all
three retry branches, while preserving logging, counter updates, and immediate
termination after the final attempt.
- Around line 245-246: Update the transient-status matching logic near the
pattern construction in SlurmSystem so blank or whitespace-only entries from
extra_transient_status_errors cannot match every stderr value. Filter invalid
patterns before any(p in stderr for p in patterns), and enforce the same
nonblank constraint at the configuration/model boundary if that validation
mechanism is available.
- Line 114: Constrain the status_retry_pause_seconds configuration field to
non-negative values by adding the appropriate ge=0 validation metadata to its
declaration. Preserve the existing integer type and default value.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 1cc623a7-c98b-4534-8604-eb6f2805f9e0
📒 Files selected for processing (3)
src/cloudai/systems/slurm/slurm_system.pytests/conftest.pytests/systems/slurm/test_system.py
The pause also ran after the final failed attempt, right before the loop terminates — a dead 10 s added to every terminal failure. Guard the sleep with retry_count < retry_threshold at all three sites. Signed-off-by: Ilya Yanok <iyanok@nvidia.com>
Reject blank/whitespace extra_transient_status_errors entries at the
model boundary and skip them in the matcher ("" in stderr is always
true — one blank pattern would turn every status result transient).
Constrain status_retry_pause_seconds to ge=0. Tests for both plus the
final-attempt pause guard.
Signed-off-by: Ilya Yanok <iyanok@nvidia.com>
There was a problem hiding this comment.
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 `@src/cloudai/systems/slurm/slurm_system.py`:
- Around line 373-378: Update the transient-error retry flow in get_job_status
so that when _is_transient_status_error(stderr) remains true after
retry_threshold attempts, it raises the underlying failure instead of falling
through to return an empty status list. Preserve the existing retry delay and
continue behavior for attempts that still have retries available, matching the
exhausted-failure handling used by is_job_running and is_job_completed.
In `@tests/systems/slurm/test_system.py`:
- Around line 294-303: Extend test_no_pause_after_final_retry to cover
is_job_completed and get_job_status as well as is_job_running, preferably by
parameterizing the status-query method while preserving the existing retry setup
and expected RuntimeError. Assert each method sleeps exactly twice for
retry_threshold=3, confirming no pause occurs after the terminal attempt.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 65a89542-2bb7-49a6-9455-d41967df7cd6
📒 Files selected for processing (2)
src/cloudai/systems/slurm/slurm_system.pytests/systems/slurm/test_system.py
Summary
SlurmSystemretries job-status queries (is_job_running,is_job_completed,get_job_status) on known transient errors — butthe loop re-runs
sacctimmediately and the error list is fixed. Asingle status hiccup can raise out of
monitor_jobsand kill amulti-hour scenario whose job is fine.
Two gaps, one goal:
1. Fast-failing transients exhaust the retry budget in under a
second.
Socket timed outself-paces (the client blocks ~10 s perattempt), but fast failures — e.g. connection refused while
slurmctld/slurmdbdrestarts — return in milliseconds, soretry_threshold=3only tolerates failures shorter than oneback-to-back
sacctinvocation. This PR pauses between attempts(
status_retry_pause_seconds, default 10 s, the order of slurm'smessage timeout): three attempts now span ~30 s, inside the default
monitor_interval = 60cadence. The sleep only runs after a failedattempt.
2. The pattern list can't know site-specific errors. Sites
wrapping the slurm CLIs (proxies, split login-node shims) emit their
own transient transport errors, which today bypass the retry entirely.
extra_transient_status_errorslets the system config extend theretryable set:
The first commit extracts a shared
_is_transient_status_error(): thecheck existed in three drifting copies (
get_job_statuswas alreadyout of sync), and both fixes need one point of truth.
Test Plan
tests/systems/slurm/test_system.py— 71 passed; retry testsstay instant (fixture pins the pause to 0); new test covers the
extra-patterns path.
ruff check/ruff formatclean.benchmarking harness since 2026-07-15; multi-hour sweeps now survive
status hiccups that previously killed them.
Additional Notes
change) → pause → config extension.
retry_threshold=3undera 60 s monitoring cadence, three evenly spaced attempts over ~30 s
already cover the observed transient windows.