Skip to content

[KV Offloading] Detect and clean up stalled transfer jobs - #46019

Closed
Alex-ai-future wants to merge 4 commits into
vllm-project:mainfrom
Alex-ai-future:feature/stalled-transfer
Closed

Alex-ai-future wants to merge 4 commits into
vllm-project:mainfrom
Alex-ai-future:feature/stalled-transfer

Conversation

@Alex-ai-future

@Alex-ai-future Alex-ai-future commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Problem

KV Offloading transfer jobs (store/load) can stall indefinitely when workers fail to report completion due to GPU hangs, CUDA driver bugs, or network failures. Without detection, stalled jobs cause cascading resource leaks:

  • _blocks_being_loaded permanently occupied → other requests can't load those blocks
  • Block ref_cnt stuck at -1 → GPU memory blocks can't be freed
  • _req_status grows unbounded → memory leak
  • Only recovery is reset_cache() → full stop, discarding all offloaded blocks

Solution

Add stalled transfer detection to OffloadingConnectorScheduler. Jobs exceeding a 300s timeout are automatically cleaned up.

Key design decisions

  1. success=False for stalled stores: Stalled store data may be incomplete. Using success=False ensures the manager discards the data rather than marking it as stored. Other requests will re-offload from scratch instead of loading corrupt data.

  2. _stalled_job_ids as dict[int, int]: After stalled cleanup, late worker reports may still arrive. The dict tracks remaining worker count per job so late reports decrement cleanly to 0, avoiding KeyError in multi-worker scenarios.

  3. Throttled stall check (10s interval): Avoids traversing all jobs on every update_connector_output call.

  4. _complete_job shared cleanup path: Extracted from both normal and stalled completion paths to eliminate ~45 lines of code duplication. The shared method does not call on_request_finished — that is request_finished()'s responsibility, not the job cleanup path's.

Testing

11 tests covering:

Test Path
test_stalled_store_job_detected Store timeout → complete_store(success=False)
test_stalled_load_unblocks_being_loaded Load timeout → _blocks_being_loaded released
test_stalled_job_skips_late_worker_report Late report doesn't trigger KeyError
test_stalled_job_with_missing_req_status req_status=None edge case
test_stall_check_is_throttled 10s throttle verification
test_reset_cache_clears_stalled_job_state reset_cache clears stalled state
test_stalled_job_no_double_on_request_finished on_request_finished not called from job cleanup
test_normal_load_completes_clears_blocks_being_loaded Normal load path cleanup
test_normal_last_job_deletes_req_status Normal path _req_status deletion
test_complete_job_clears_block_id_to_pending_jobs Fence cleanup
test_stalled_load_does_not_pass_success complete_load without success kwarg
.venv/bin/python -m pytest tests/v1/kv_connector/unit/offloading_connector/test_scheduler.py -v

Follow-ups

  • Configurable timeout: The 300s timeout is currently hardcoded. A follow-up will make it configurable via OffloadingSpec.
  • Stalled transfer metrics: Currently only logger.error is emitted. A follow-up will add a stalled_transfers_total counter for observability and alerting.

Roadmap

Part of KV Offloading roadmap (#33689).

@mergify

mergify Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @Alex-ai-future.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jun 21, 2026
@Alex-ai-future
Alex-ai-future force-pushed the feature/stalled-transfer branch from c5d741f to 93ca166 Compare June 22, 2026 03:42
@mergify mergify Bot removed the needs-rebase label Jun 22, 2026
@mergify

mergify Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @Alex-ai-future.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jun 22, 2026
@Alex-ai-future
Alex-ai-future force-pushed the feature/stalled-transfer branch from 93ca166 to 0988542 Compare June 22, 2026 08:08
@mergify mergify Bot removed the needs-rebase label Jun 22, 2026
@Alex-ai-future
Alex-ai-future force-pushed the feature/stalled-transfer branch 2 times, most recently from aef4861 to af8f340 Compare June 29, 2026 06:06
Add stalled transfer detection to prevent cascading resource leaks
when workers fail to report completion. Jobs exceeding 300s timeout
are automatically cleaned up with success=False to discard potentially
incomplete data.

Key design decisions:
- Stalled store jobs use success=False so blocks are not marked as
  stored and can be re-offloaded
- _stalled_job_ids (dict) tracks remaining worker count for late
  report handling, avoiding KeyError in multi-worker scenarios
- Stall check is throttled to 10s intervals

11 tests cover store/load cleanup, late worker reports, missing
req_status edge cases, throttle verification, and reset_cache state
clearing.

Signed-off-by: Alex <alex.tech.lab@outlook.com>
Extract shared cleanup logic from _handle_stalled_job and
update_connector_output into _complete_job. This removes ~45 lines
of duplicated code and fixes a bug where _handle_stalled_job called
on_request_finished a second time — request_finished() already
notified the manager, so the duplicate call could cause KeyError or
premature secondary tier cleanup in TieringManager.

Added 5 tests covering both normal and stalled paths through
_complete_job: _blocks_being_loaded cleanup, _req_status deletion,
_block_id_to_pending_jobs cleanup, and on_request_finished
non-invocation.

Signed-off-by: Alex <alex.tech.lab@outlook.com>
@mergify

mergify Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @Alex-ai-future.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jul 7, 2026
Signed-off-by: Alex <alex.tech.lab@outlook.com>
@mergify mergify Bot removed the needs-rebase label Jul 8, 2026
Signed-off-by: Alex <alex.tech.lab@outlook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant