Почему мое представление Django зависает, когда я использую asyncio.gather при вызове функции sync_to_async, но не когда я вызываю ее напрямую?

У меня есть представление Django, которое вызывает функцию asgiref.sync.async_to_sync, которая запрашивает удаленный API - я обновляю данные о зарплате для кучи сотрудников. В рамках одного из этих вызовов мне нужно снова обратиться к БД, поэтому у меня есть декорированная функция asgiref.sync.sync_to_async для сбора этих данных. Я запускаю вызовы функции обновления сотрудников одновременно с помощью asyncio.gather, но она зависает на неопределенное время и даже не входит в вызов БД - это происходит, даже если у меня только один вызов в списке сбора. Ожидание функции работает нормально. Все работает как ASGI приложение под Uvicorn. Есть идеи?

Вот минимальное воспроизведение:

@sync_to_async
def _get_database_employee_payslips(employee_data):
    print(f"Entering DB function")
    return employee_data

@async_to_sync
async def get_full_employees_data(_, __):
    print(f"This works")
    ret = await _get_database_employee_payslips({'id': 1625841})
    print(f"Got {ret}")

    print(f"This doesn't")
    ret = await asyncio.gather(*[
        _get_database_employee_payslips({'id': employee_id})
        for employee_id in [1625841]
    ], return_exceptions=True)    
    print(f"We're hung in the above call")

    return ret

и результаты:

INFO 2022-09-27 14:20:20,234 on 10776 140271592661440 Application startup complete.
DEBUG 2022-09-27 14:20:22,163 middleware 10776 140271484180032 process_request
DEBUG 2022-09-27 14:20:22,163 model_factory 10776 140271484180032 No maximum request body size is set, continuing.
DEBUG 2022-09-27 14:20:22,183 model_factory 10776 140271484180032 Created new request model with pk 161dfa90-4082-4ef1-8ab0-84d613c25550
This works
Entering DB function
Got {'id': 1625841}
This doesn't

Окружение:

  • WSL2
  • Ubuntu 22.04.1 LTS
  • .
  • Python 3.10.4
  • .

Пакеты Python (только те, которые кажутся актуальными):

aiohttp==3.8.3
aiosignal==1.2.0
anyio==3.6.1
asgiref==3.5.2
async-timeout==4.0.2
asyncio==3.4.3
Django==4.1.1
uvicorn==0.18.3
uvloop==0.17.0
uWSGI==2.0.20

Похоже, это известная проблема - вложение async_to_sync и sync_to_async может привести к неопределенному зависанию вызова, см. https://code.djangoproject.com/ticket/32409

Вернуться на верх