[Bugfix] Compensate cancelled duplex open, append and resume; fix serving README drift (#7636 Issues 1, 2, 3, 21) (#7785)

Signed-off-by: chickeyton <ngton2014@gmail.com>
Signed-off-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-09-24 19:23:08 -07:00
1 parent 551a03102f
commit 9e7e3a802c
19 files changed
+1697 -96

No files matched your search

+21 -2
View File
@@ -20,7 +20,7 @@ from __future__ import annotations
import asyncio
from collections.abc import Awaitable, Callable
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Protocol, TypeVar
from typing import TYPE_CHECKING, Any, Protocol, TypeVar
if TYPE_CHECKING:
from vllm.outputs import RequestOutput
@@ -117,6 +117,10 @@ class DuplexSessionTasks:
append_tasks: dict[asyncio.Task[bool], DuplexAppendTaskMeta] = field(default_factory=dict)
append_tail: asyncio.Task[bool] | None = None
active_response_task: asyncio.Task[None] | None = None
#: Appends the runner cancelled on purpose (a cancel, barge-in or close).
#: The runner ends the response such an append precreated, so the append
#: leaves it alone on its way out instead of failing it.
runner_cancelled: set[asyncio.Task[bool]] = field(default_factory=set)
def track_append_task(
self,
@@ -127,16 +131,31 @@ class DuplexSessionTasks:
response_bound: bool,
) -> None:
self.append_tasks[task] = DuplexAppendTaskMeta(epoch, final, response_bound)
task.add_done_callback(self.append_tasks.pop)
task.add_done_callback(self._forget_append_task)
def _forget_append_task(self, task: asyncio.Task[bool]) -> None:
self.append_tasks.pop(task, None)
self.runner_cancelled.discard(task)
def cancelled_by_runner(self, task: asyncio.Task[Any] | None) -> bool:
"""Whether ``task`` is an append the runner cancelled through ``cancel_append_tasks``."""
return task is not None and task in self.runner_cancelled
def has_response_bound_append_tasks(self) -> bool:
return any(meta.response_bound for meta in self.append_tasks.values())
async def cancel_append_tasks(self, timeout_s: float = 0.25, *, response_bound_only: bool = False) -> bool:
"""Cancel the tracked appends; the caller owns their responses from here on.
Every caller ends the active response itself right after (with the
cancel status, or silently as part of a close), so the cancelled
appends are told not to fail the response they precreated.
"""
tasks = [task for task, meta in self.append_tasks.items() if not response_bound_only or meta.response_bound]
if not tasks:
return False
cancelled_tail = self.append_tail if self.append_tail in tasks else None
self.runner_cancelled.update(tasks)
for task in tasks:
task.cancel()
try: