Repository navigation
MAINT: Clean up sibling token-region conversions on failure (P311-11) - #3980
Merged
Roman Lutz (romanlutz) merged 3 commits intoNov 6, 2026
Merged
Roman Lutz (romanlutz) merged 3 commits into
Roman Lutz (romanlutz) merged 3 commits into
Conversation
Selected token regions ran under a bare asyncio.gather, so when one region failed the error reached the caller while the other regions kept running unowned. Those regions can still call a target or write a file after the caller has already handled the failure or retried. Await them with gather_with_cleanup_async, which cancels and drains the siblings before re-raising the first error. Region order, error identity, caller cancellation and the caller's cancellation count are unchanged.
10 of 25 tasks
Roman Lutz (romanlutz)
self-requested a review
November 5, 2026 15:01
Contributor
Author
|
@microsoft-github-policy-service agree |
Roman Lutz (romanlutz)
approved these changes
Nov 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Part of #3166 (P311-11): the selected-region case in
Converter._convert_token_regions_async.Selected regions ran under a bare
asyncio.gather. When one region failed, the error reached the caller while the other regions kept running unowned. A region can call a target or write a file, so a request could still be sent, or a file written, after the caller had handled the failure or started a retry. This applies toconvert_tokens_asyncand toSelectiveTextConverter, which share this code path.This PR awaits the regions with the existing
gather_with_cleanup_asynchelper, so the first failure cancels the regions still running and waits for their cleanup before the original error is raised.I used the helper rather than a new
asyncio.TaskGroupbecause it already gives the behaviour this item asks for:ExceptionGroupto unwrapA plain
TaskGroupin this method fails the new cancellation-count test on Python 3.11. Scope is this one site.pyrit/common/task_utils.pyand othergathercall sites are unchanged. The result is the same as before when no region fails.Conversions already running in a worker thread cannot be interrupted, so cancellation only stops the awaiting task in that case.
Reproduction
Before:
After:
Tests and Documentation
New tests:
test_convert_tokens_failed_region_cancels_in_flight_regions_async: a failing region cancels its sibling, the sibling's cleanup finishes before the caller sees the error, and the exact original exception (with its__cause__) is raised. Fails onmain.test_token_selection_failed_region_cancels_in_flight_regions_async: a failing region cancels its sibling when conversion runs throughSelectiveTextConverter, and the original exception is raised. Fails onmain.test_convert_tokens_out_of_order_completion_keeps_region_order_async: regions that finish in reverse order are still assembled in source order.test_convert_tokens_failure_preserves_caller_cancellation_count_async: repeated failures leaveTask.cancelling()unchanged.test_convert_tokens_caller_cancellation_drains_regions_async: external cancellation cancels every region, keeps the cancellation message, and leaves a count of 1.The last three pass on
maintoo and pin behaviour that must not change. To check that the tests catch real regressions, I temporarily swapped in four wrong implementations on Python 3.11, and each failed at least two of the new tests:TaskGroup, and aTaskGroupthat unwraps the group: failed the cancellation-count test and the failure testResults on the commit before rebasing onto current
main, which only added an unrelatedTemplateSegmentConverterchange. After the rebase I rerantest_converter.py,test_selective_text_converter.pyandtest_async_utils.pyon Python 3.11: 344 passed, 2 skipped.pytest tests/unit/converter tests/unit/prompt_normalizer tests/unit/test_async_utils.py tests/unit/backend/test_converter_service.py tests/unit/backend/test_message_send_service.py -n 2 --dist=loadfile: 3587 passed, 48 skipped.pytest tests/unit/common tests/unit/registry tests/unit/executor/promptgen -n 2 --dist=loadfile: 2214 passed, 17 skipped, 4 xfailed.pytest tests/unit/converter/test_converter.py tests/unit/converter/test_selective_text_converter.py tests/unit/test_async_utils.py: 344 passed, 2 skipped on each.ruff checkandruff format --checkon the changed files: passed.ty checkon the changed files: passed, without optional extras.pre-commit run --fileson the changed files: passed, with thety-checkhook skipped because it needs--extra all.Not run: the full
make unit-testsuite,make tywith--extra all, and tests that need optional dependencies, which account for the skips. No live target was used.Documentation: the
convert_tokens_asyncdocstring now states the failure behaviour. The converter notebooks do not describe failures and are unchanged.JupyText: not run. No notebook or doc page changed, and conversion output is unchanged when every region succeeds.