Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions lib/bindings/python/tests/cancellation/test_cancellation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
pytest.mark.gpu_0,
pytest.mark.pre_merge,
pytest.mark.unit,
pytest.mark.timeout(30),
]


Expand All @@ -23,6 +24,7 @@ def __init__(self):
self.context_is_stopped = False
self.context_is_killed = False
self.context_metadata: dict[str, str] = {}
self.context_cancelled = asyncio.Event()

async def generate(self, request, context):
print("################## generate called ######################")
Expand Down Expand Up @@ -53,13 +55,15 @@ async def _generate_until_context_cancelled(self, request, context):
self.context_is_stopped = True
self.context_is_killed = context.is_killed()
self.context_metadata = dict(context.metadata.items())
self.context_cancelled.set()
Comment thread
jthomson04 marked this conversation as resolved.
raise asyncio.CancelledError

if context.is_killed():
print(f"Context killed at iteration {i}")
self.context_is_stopped = context.is_stopped()
self.context_is_killed = True
self.context_metadata = dict(context.metadata.items())
self.context_cancelled.set()
raise asyncio.CancelledError

await asyncio.sleep(0.1)
Expand All @@ -83,13 +87,15 @@ async def _generate_until_context_cancelled_with_metadata(self, request, context
self.context_is_stopped = True
self.context_is_killed = context.is_killed()
self.context_metadata = dict(context.metadata.items())
self.context_cancelled.set()
raise asyncio.CancelledError

if context.is_killed():
print(f"Context killed at iteration {i}")
self.context_is_stopped = context.is_stopped()
self.context_is_killed = True
self.context_metadata = dict(context.metadata.items())
self.context_cancelled.set()
raise asyncio.CancelledError

await asyncio.sleep(0.1)
Expand Down Expand Up @@ -221,8 +227,7 @@ async def test_client_context_cancel(temp_file_store, server, client):

iteration_count += 1

# Give server a moment to process the cancellation
await asyncio.sleep(0.2)
await asyncio.wait_for(handler.context_cancelled.wait(), timeout=5)

# Verify server detected the cancellation
assert handler.context_is_stopped
Expand Down Expand Up @@ -256,7 +261,7 @@ async def test_client_context_cancel_preserves_metadata(

iteration_count += 1

await asyncio.sleep(0.2)
await asyncio.wait_for(handler.context_cancelled.wait(), timeout=5)

assert handler.context_is_stopped
assert not handler.context_is_killed
Expand Down Expand Up @@ -350,6 +355,18 @@ async def test_server_raise_cancelled(temp_file_store, server, client):
assert not handler.context_is_killed


async def _wait_for_cancelled_request(request, handler):
stream = await request
Comment thread
jthomson04 marked this conversation as resolved.
# Cancellation propagates asynchronously, so responses can arrive before it completes.
try:
async for _ in stream:
pass
except ValueError as error:
if str(error) != "Cancelled: CancelledError":
raise
await handler.context_cancelled.wait()
Comment thread
jthomson04 marked this conversation as resolved.


@pytest.mark.forked
@pytest.mark.asyncio
@pytest.mark.parametrize("request_plane", ["nats", "tcp"], indirect=True)
Comment thread
jthomson04 marked this conversation as resolved.
Expand All @@ -358,15 +375,8 @@ async def test_client_context_already_cancelled(temp_file_store, server, client)
context = Context()
context.stop_generating()
# TODO: (DIS-830) The outgoing call should raise if context is cancelled
stream = await client.generate("_generate_until_context_cancelled", context=context)

async for _ in stream:
raise AssertionError(
"Request should be cancelled before any responses are generated"
)

# Give server a moment to update status
await asyncio.sleep(0.2)
request = client.generate("_generate_until_context_cancelled", context=context)
await asyncio.wait_for(_wait_for_cancelled_request(request, handler), timeout=5)
Comment thread
jthomson04 marked this conversation as resolved.

# Verify server context cancellation status
assert handler.context_is_stopped
Expand All @@ -384,15 +394,7 @@ async def test_client_context_cancel_before_await_request(
request = client.generate("_generate_until_context_cancelled", context=context)
context.stop_generating()
# TODO: (DIS-830) The outgoing call should raise if context is cancelled
stream = await request

async for _ in stream:
raise AssertionError(
"Request should be cancelled before any responses are generated"
)

# Give server a moment to update status
await asyncio.sleep(0.2)
await asyncio.wait_for(_wait_for_cancelled_request(request, handler), timeout=5)
Comment thread
jthomson04 marked this conversation as resolved.

# Verify server context cancellation status
assert handler.context_is_stopped
Expand Down
Loading