Почему асинхронный пост-сохранение Django Signals блокирует другие асинхронные вызовы ORM?

У меня есть приложение Django 5, использующее веб-сокеты с помощью channels, и я пытаюсь перейти на AsyncConsumers, чтобы использовать преимущества асинхронного выполнения для ввода-вывода или внешних задач API.

Я уже написал демо-проект и все работает нормально, однако в моем приложении я использую Django signals, и у меня есть длинная задача ввода-вывода, которая должна быть выполнена в post_save из MyModel, ранее реализованная с помощью потоков:

from asyncio import sleep

@receiver(dj_models.signals.post_save, sender=MyModel)
async def auto_process_on_change(sender, instance, **kwargs):
  logger.log("Starting Long Save task");
  await sleep(30)
  logger.log("Starting Long Save task");

Потребитель websocket, обслуживающий запрос, выглядит следующим образом:

from channels.generic import websocket

class AsyncGenericConsumer(websocket.AsyncJsonWebsocketConsumer):

   async def connect(self):
      await self.accept()
   
   ...
   
   async def receive_json(self, message):
      ...
      user = await User.objects.aget(id=...)
      # Authentication code
      # ....
      # (eventually) Create MyModel, depending on request type
      mod = await my_models.MyModel.objects.acreate(...)

Теперь проблема заключается в следующем:

Когда запрос Alice все еще выполняет операцию post_save (т.е, ожидая выполнения содержащейся в нем длинной задачи), а пользователь Bob открывает браузер и делает запрос к тому же потребителю, вычисление застревает на user = await User.objects.aget(id=...) до тех пор, пока длинная задача (например, asyncio.sleep(30)) не завершится для Алисы.

Реальное приложение намного сложнее, чем это, и мы не можем избавиться от post_save. Я хотел бы понять, как .aget() на модели может быть заблокирован post_save на другой модели, когда они должны быть асинхронными вызовами и обрабатываться как таковые. Есть ли способы избежать этого, продолжая использовать код asyncio?

Я использую последние версии всех задействованных пакетов.

Спасибо за поддержку.

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