From 40268b0a6aa592ebe536739508d4adf57a387a37 Mon Sep 17 00:00:00 2001 From: MyButtermilk Date: Tue, 6 Oct 2026 15:21:21 +0200 Subject: [PATCH] Observe canceled Meeting stop settlement without recanceling it --- docs/TESTING_AND_RELEASE.md | 6 +++++- tests/test_meeting_api.py | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/TESTING_AND_RELEASE.md b/docs/TESTING_AND_RELEASE.md index 5958a720..e9f7f4a3 100644 --- a/docs/TESTING_AND_RELEASE.md +++ b/docs/TESTING_AND_RELEASE.md @@ -143,7 +143,11 @@ zero unobserved `shield`/Future exception contexts. HTTP seam: invalid start commands fail before admission; repeated cancellation cannot skip cleanup or lease release; and Stop reserves a finalizer before native shutdown, commits `finalizing`, opens the worker gate, then delivers the -pending cancellation. +pending cancellation. The real SQLite-lock cancellation test observes task +completion with a bounded `asyncio.wait`, then checks `CancelledError` separately; +its observer must not inject another cancellation through `wait_for`. The +ten-second settlement guard permits Windows CI scheduling delays while still +rejecting stranded work and retaining all lease/finalizer/recorder assertions. `tests/api/test_meeting_capture_routes.py` registers the extracted start, pause, resume, and stop routes, proves normalization into one immutable start command, pins the four-method controller port, and verifies that `create_app` diff --git a/tests/test_meeting_api.py b/tests/test_meeting_api.py index 0eead8be..6ec48902 100644 --- a/tests/test_meeting_api.py +++ b/tests/test_meeting_api.py @@ -2440,8 +2440,14 @@ def contended_release(target): assert recorder.stop_count == 1 return if request_end == "cancel": + # Observe the cancellation already requested above. wait_for would + # inject another cancellation on slow Windows CI and translate the + # expected CancelledError into TimeoutError, obscuring settlement. + # This is a lifecycle assertion, not a two-second latency budget. + done, _ = await asyncio.wait({request_task}, timeout=10) + assert request_task in done, "Meeting stop did not settle after releasing the database lock" with pytest.raises(asyncio.CancelledError): - await asyncio.wait_for(request_task, 2) + await request_task elif request_end == "response": assert (await asyncio.wait_for(request_task, 2)).status == 202 await asyncio.wait_for(finalizer_started.wait(), 2)