Поток uWSGI имеет существующий запущенный цикл событий, который вызывает исключение Django SynchronousOnlyOperation
У меня есть два представления Django,
def view_that_accesses_orm(request): # say end point /useorm
user = User.objects.first()
...
и
def view_that_creates_event_loop(request): # say endpoint /createloop
client = AsycProvider()
... # do stuff with client
и AsyncProvider
- это что-то вроде
class AsyncProvider:
def __init__(self):
try:
self.__loop = asyncio.get_event_loop()
except RuntimeError as e:
print(e) #no running event loop
self.__loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.__loop)
self.__session = aiohttp.ClientSession(loop=self.__loop)
... # other operations with asyncio.run_until_complete, asyncio.gather, and self.__session
Теперь проблема в том, что, скажем, если у меня есть 1 процесс в uWSGI и 2 потока. Тогда они будут обслуживать запросы по кругу.
Итак, сценарий таков:
- User hits
/createloop
(given thread 1) - User hits
/useorm
(given thread 2) - User again hits
/useorm
(given thread 1)
Теперь третий сценарий, иногда цикл событий запущен, и поскольку Django 3.x обнаруживает запущенный цикл событий и запрещает нам доступ к ORM, я получаю django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
исключение.
Я не уверен, как цикл событий не останавливается и сохраняется в потоке.
Пожалуйста, объясните, что именно может быть причиной этого и что следует исправить?
Проблема заключалась в том, что где-то внутри метода AsyncProvider
использовался метод asyncio.set_event_loop(self.__loop)
.
Таким образом, на один и тот же экземпляр цикла ссылались в разных потоках (новый цикл не создавался). Теперь, поскольку в этом цикле иногда выполнялась логика, а также если в потоке (который ссылался на этот цикл) происходило обращение к ORM, Django бросал SynchronousOnlyOperation
, поскольку мог обнаружить работающий цикл событий.
Решил ее, удалив asyncio.set_event_loop(self.__loop)
в методе.