fix(backend/copilot): only count tasks as cancelled when CancelledError is raised

The cancelled counter was incrementing for both asyncio.CancelledError and
asyncio.TimeoutError. Tasks that don't respond to cancellation within 5s now
correctly report as not cancelled. Also adds a test covering the timeout path.
This commit is contained in:
majdyz
2026-04-15 10:54:48 +07:00
parent db45cad1b5
commit 4ac231ce59
2 changed files with 23 additions and 2 deletions

View File

@@ -1186,11 +1186,12 @@ async def disconnect_all_listeners(session_id: str) -> int:
for _qid, task in to_cancel:
try:
await asyncio.wait_for(task, timeout=5.0)
except (asyncio.CancelledError, asyncio.TimeoutError):
except asyncio.CancelledError:
cancelled += 1
except asyncio.TimeoutError:
pass
except Exception as e:
logger.error(f"Error cancelling listener for session {session_id}: {e}")
cancelled += 1
if cancelled:
logger.info(f"Disconnected {cancelled} listener(s) for session {session_id}")

View File

@@ -1,6 +1,7 @@
"""Tests for disconnect_all_listeners in stream_registry."""
import asyncio
from unittest.mock import AsyncMock, patch
import pytest
@@ -88,3 +89,22 @@ async def test_disconnect_all_listeners_skips_already_done_tasks():
async def test_disconnect_all_listeners_empty_registry():
cancelled = await stream_registry.disconnect_all_listeners("sess-1")
assert cancelled == 0
@pytest.mark.asyncio
async def test_disconnect_all_listeners_timeout_not_counted():
"""Tasks that don't respond to cancellation (timeout) are not counted."""
task = asyncio.create_task(_sleep_forever())
stream_registry._listener_sessions[1] = ("sess-1", task)
with patch.object(
asyncio, "wait_for", new=AsyncMock(side_effect=asyncio.TimeoutError)
):
cancelled = await stream_registry.disconnect_all_listeners("sess-1")
assert cancelled == 0
task.cancel()
try:
await task
except asyncio.CancelledError:
pass