Кажется я столкнулся с некоторым "несовершенством" в архитектуре asyncio.
Там есть такая штука, как возможность отменить корутину. Физически это делается так, что когда мы вызваем метод cancel() для корутины, то это вызывает исключение CancelledError в корутине, но не в той для которой мы вызвали отмену, а в самой последней в цепочке корутин, которые в данный момент await-ся из родительской корутины. И далее это исключение по этой же цепочке, в обратном направлении, поднимается до самой первой корутины.
"Несовершенство" заключается в том, что нельзя понять где именно "произошла" отмена корутины. Это может быть какая-то верхнеуровневая корутина, которая по каким-то причинам отменила свою "дочернюю" корутину (таймаут или клиент разорвал конект). Или это исключение случилось по другим причинам где-то в глубине цепочки корутин.
Проблема с этим заключается в том, что не понятно как обрабатывать это исключение в каком-то промежуточном слое, который находится, например, между веб-сервером и вьюшкой обрабатывающей запрос. Вот есть у меня в aiohttp миделвара, которая логирует исключения, которые прилетели из вьюшек. И иногда прилетает CancelledError. И я не могу определить - это веб-сервер иницировал это исключение из-за того что произошёл обрыв конекта, или что-то реально случилось внутри вьюшки. В первом случае мне ничего делать не надо - просто прокинуть исключение дальше. Во втором мне надо залогировать ошибку, и вернуть клиенту корректный HTTP-ответ (500-ую ошибку).