Сравнение конкурентности в разных языках обычно начинают с синтаксиса. Я бы начал с того, что нужно расчёту, когда что-то падает.
Небольшое приложение на Python параллельно загружает измерения и веса и объединяет их в одну оценку. Одна загрузка выбрасывает исключение, пока другая ещё выполняется.
Первый шаг. Делает ли одна неудачная загрузка весь расчёт бесполезным? Если да, подходит asyncio.TaskGroup. Когда участник группы падает с любым исключением, кроме CancelledError, группа отменяет остальных участников и дожидается своих задач, прежде чем завершить выход. Одно легко упустить. Сам вызов корутинной функции ничего не планирует, поэтому загрузки нужно оформить как задачи в группе.
Второй шаг, и решение здесь другое. Обе задачи вернулись нормально, но веса не годятся. Сбор завершён. Теперь посмотрим, что пришло. Отклонить входные данные, запросить замену или выдать частичный результат? TaskGroup это за нас не решает.
Третий шаг, отмена со стороны вызывающего. Код очистки в загрузках должен пропускать CancelledError дальше. Если его проглотить, поведение отмены в группе может нарушиться.
Для этого приложения я выбираю TaskGroup, потому что сбой любой загрузки завершает общий запрос, а область должна дождаться своих участников. Проверка полученных данных идёт следом, до любого расчёта. Это и есть то конкретное, что сравнение с другими языками должно сохранить.
