Django Асинхронные каналы, блокирующие Websocket
У меня возникла проблема с каналами django, которую я не смог решить. В принципе, у меня есть пошаговая боевая система, где сообщения принимаются от клиента, чтобы сигнализировать, например, о наступлении хода противника. Это происходит через потребителя:
async def receive(self, text_data):
data = json.loads(text_data)
message_type = data.get('type')
if message_type == 'enemy_combat_turn':
await self.handle_end_of_turn(data)
async def handle_end_of_turn(self, data):
npc_name = data.get('npc_name')
debuff = data.get('debuff')
combat_message = data.get('combat_message')
print(f"Handling end of combat turn for player. Initiating enemy turn next.")
# Check for active traps first
response = await trigger_trap(game_id=self.game_id,
npc_name=npc_name)
# Then, trigger enemy combat action
response = await sync_to_async(enemy_combat_action)
(self.game_id, npc_name, debuff, combat_message)
async def send_unified_message(self, event):
# Send message to WebSocket
await self.send(text_data=json.dumps(event))
print(f"Sending message for event {event}")
Потребитель ожидает несколько асинхронных функций, например, результат handle_end_of_turn, который состоит из двух других асинхронных функций, trigger_trap и enemy_combat_action.
Теперь в trigger_trap и в enemy_combat_action мы отправляем сообщения обратно клиенту, например:
# Send trap message
async_to_sync(channel_layer.group_send)(
f'character_{game_id}',
{
'type': 'send_unified_message',
'message_type': 'new_assistant_messages',
'messages': trap_message,
}
)
Поскольку функции определены асинхронно, ожидается, что сообщения будут отправляться немедленно, но вместо этого они, похоже, ставятся в очередь и отправляются все одновременно, как только все результаты вызовов функций будут дожданы и возвращены в главный цикл событий, который, похоже, является самим потребителем. Моя гипотеза заключается в том, что это происходит потому, что send_unified_message блокируется от выполнения, поскольку мы все еще ожидаем результатов от других асинхронных функций.
Что я могу сделать, чтобы обойти это? Я пытаюсь заставить его работать последние 4 часа, но у меня больше нет идей...