[Bugfix] Fix colocate-async sleep admission race and deliver AR abort tokens (#6367)

Signed-off-by: knlnguyen1802 <knlnguyen1802@gmail.com>
Signed-off-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Samit <285365963@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Samit <285365963@qq.com>
This commit is contained in:
authored and GitHub committed 2026-08-29 09:11:39 +00:00
1 parent 5c47fd0bc8
commit bb5bf8fd0a
23 files changed
+1229 -157

No files matched your search

+91 -3
View File
@@ -180,7 +180,6 @@ def test_abort_handles_internal_request_mapping(req_ids: list[str], cancel_prefi
assert re.fullmatch(rf"{re.escape(cancel_prefix)}-[0-9a-f]+", rid)
assert len(aborted_ids) == expected_cancel_count
assert len(set(aborted_ids)) == expected_cancel_count
assert len(omni.request_states) == len(req_ids) - expected_cancel_count
for t in tasks:
t.cancel()
@@ -190,7 +189,9 @@ def test_abort_handles_internal_request_mapping(req_ids: list[str], cancel_prefi
@pytest.mark.cpu
def test_abort_pops_request_states_only_after_ack():
def test_abort_keeps_request_states_until_generate_cleanup():
"""Frontend abort must not drop request_states; generate() owns cleanup."""
async def run():
release = asyncio.Event()
seen_during_wait: list[int] = []
@@ -215,7 +216,7 @@ def test_abort_pops_request_states_only_after_ack():
release.set()
await task
assert "req-1-aaaa" not in omni.request_states
assert "req-1-aaaa" in omni.request_states
asyncio.run(run())
@@ -241,6 +242,93 @@ def test_abort_propagates_engine_errors_without_popping_state():
asyncio.run(run())
@pytest.mark.cpu
def test_abort_enqueues_prefix_tokens_from_engine():
"""AR abort must deliver the generated prefix on the request queue (CPU)."""
async def run():
from vllm.outputs import CompletionOutput
from vllm_omni.engine.messages import OutputMessage
queue: asyncio.Queue = asyncio.Queue()
async def abort_with_prefix(request_ids):
rid = request_ids[0]
engine_output = OmniRequestOutput(
request_id=rid,
finished=True,
stage_id=0,
final_output_type="text",
outputs=[
CompletionOutput(
index=0,
text="partial",
token_ids=[7, 8, 9],
cumulative_logprob=None,
logprobs=None,
finish_reason="abort",
stop_reason=None,
)
],
)
return [
OutputMessage(
request_id=rid,
stage_id=0,
replica_id=None,
engine_outputs=engine_output,
metrics=None,
finished=True,
stage_submit_ts=None,
)
]
omni = get_async_omni_instance(fake_abort_request=abort_with_prefix)
omni.request_states["req-1-cccc"] = SimpleNamespace(
request_id="req-1-cccc",
external_request_id="req-1",
input_stream_task=None,
queue=queue,
)
await omni._abort(["req-1-cccc"])
msg = queue.get_nowait()
assert msg.finished is True
assert list(msg.engine_outputs.outputs[0].token_ids) == [7, 8, 9]
assert msg.engine_outputs.outputs[0].finish_reason == "abort"
assert "req-1-cccc" in omni.request_states
asyncio.run(run())
@pytest.mark.cpu
def test_abort_enqueues_synthetic_finished_when_engine_returns_empty():
"""Empty abort_async must still unblock generate() with finish_reason=abort."""
async def run():
queue: asyncio.Queue = asyncio.Queue()
async def empty_abort_async(request_ids):
del request_ids
return []
omni = get_async_omni_instance(fake_abort_request=empty_abort_async)
omni.request_states["req-1-dddd"] = SimpleNamespace(
request_id="req-1-dddd",
external_request_id="req-1",
input_stream_task=None,
queue=queue,
)
await omni._abort(["req-1-dddd"])
msg = queue.get_nowait()
assert msg.finished is True
assert msg.request_id == "req-1-dddd"
assert msg.engine_outputs.outputs[0].finish_reason == "abort"
assert "req-1-dddd" in omni.request_states
asyncio.run(run())
@pytest.mark.cpu
def test_generate_accepts_request_after_repeated_cancellations():
async def run_test():