Add integration test suite: end-to-end job lifecycle + failure/recovery - #7
Open
RehanTaneja wants to merge 1 commit into
Open
Add integration test suite: end-to-end job lifecycle + failure/recovery#7RehanTaneja wants to merge 1 commit into
RehanTaneja wants to merge 1 commit into
Conversation
New tests/integration/ suite (pytest -m integration, ~1 min) that runs a
real uvicorn coordinator and real worker subprocesses per test:
- test_job_lifecycle.py: submit -> QUEUED + experiment record; invalid
input; full 2-worker lifecycle over real Gloo (auto-start, heartbeat
metrics, COMPLETED); runtime checkpoints with sha256-verified manifests;
experiment metadata reuse/mismatch; cancel.
- test_failure_recovery.py: kill worker mid-training -> LOST ->
RECOVERING -> relaunch -> checkpoint resume -> COMPLETED with a
time-to-recovery bound; all workers lost -> FAILED; deregister fast
path; max recovery attempts exhausted; silent heartbeat-drop detection.
Product changes needed to make these flows reachable end-to-end:
- Worker CLI flags for the existing failure-injection hooks
(--kill-at-step, --pause-at-step, --pause-duration,
--drop-heartbeat-rate) plus --checkpoint-interval,
--heartbeat-interval, and --disable-dist.
- Workers report saved checkpoint shards to the coordinator
(POST /api/workers/checkpoint-complete) so manifest.json is actually
written at runtime; manifest output honors the job's checkpoint_dir.
- Heartbeats carry latest step/loss/throughput so metrics aggregation
(run_summary/latest_metrics) works in real runs.
- submit_job respects submitted total_steps/checkpoint_dir instead of
hardcoding 100/"./checkpoints"; recovery relaunch forwards
checkpoint/heartbeat intervals and disable_dist.
- Jobs auto-start (QUEUED -> RUNNING) once all expected workers register.
- LOST workers no longer block job completion or manifest generation.
- New routes: GET /api/jobs/{id} (decorator was missing), GET
/api/jobs/{id}/metrics, POST /api/jobs/{id}/cancel, POST
/api/workers/checkpoint-complete.
Bug fixes uncovered by the suite:
- JobStateMachine.can_transition used a private python-statemachine API
that no longer exists (2.5.0), so jobs could never reach COMPLETED;
now uses the public allowed_events.
- restore_checkpoint failed on PyTorch >= 2.6 (weights_only default
rejects saved RNG state); load with weights_only=False.
- Resubmitting an existing run_id crashed on job_spec.deterministic
(field does not exist on JobSpec).
Also adds pytest.ini (integration marker, timeouts) and
requirements-dev.txt, and updates docs/chaos_testing.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Summary
Adds the missing integration test suite called out in
docs/chaos_testing.md: 11 tests undertests/integration/(pytest markerintegration, ~1 min) that spawn a real uvicorn coordinator and real worker subprocesses per test, with heartbeat/recovery timings shortened viaDISTROML_*env vars.Test coverage
test_job_lifecycle.pytest_failure_recovery.py(workers run--disable-dist; rationale in module docstring)POST /api/workers/deregisterfast failure path (recovery < 5s, no heartbeat wait)--drop-heartbeat-rate 1.0) detected as LOSTProduct changes required to make these flows reachable
--checkpoint-interval,--heartbeat-interval,--disable-distPOST /api/workers/checkpoint-complete) somanifest.jsonis actually generated at runtime (previously unreachable — recovery had nothing to restore from)submit_jobrespects submittedtotal_steps/checkpoint_dir(were hardcoded to 100/./checkpoints); recovery relaunch forwards the new flagsstart_job()before)GET /api/jobs/{id}(decorator was missing),GET /api/jobs/{id}/metrics,POST /api/jobs/{id}/cancel,POST /api/workers/checkpoint-completeBug fixes uncovered by the suite
JobStateMachine.can_transitionused a private python-statemachine API removed by 2.5.0 → jobs could never reach COMPLETED; now uses the publicallowed_eventsrestore_checkpointcrashed on PyTorch ≥ 2.6 (weights_only=Truedefault rejects saved RNG state) → recovery always failed; loads withweights_only=Falsejob_spec.deterministic(no such field onJobSpec)Test plan
tests/test_checkpoint_restore.pyfail onmainalready (test worker never initializes its model before restoring) — pre-existing, untouched by this PR🤖 Generated with Claude Code