Django Каналы AsyncWebSocketConsumer ConnectionClosedError 1005
Я пишу приложение django channels и заметил исключение при обработке функции heartbeat, связанное с кодом статуса websocket, для которого я не смог найти никаких существующих проблем. Это происходит в AsyncWebsocketConsumer, поддерживаемом redis.
ConnectionClosedError: websockets.exceptions.ConnectionClosedError: received 1005 (no status code [internal]); then sent 1005 (no status code [internal])
async def receive(self, text_data):
try:
if text_data == "healthcheck":
await self.send(
text_data=json.dumps({"type": "healthcheck", "data": self.group_name})
)
else:
logger.info(f"Unsupported WS Event: {text_data}")
pass
except:
logger.exception("Failed to handle message from client")
Также получаем эту ошибку
RuntimeError: RuntimeError: Unexpected ASGI message 'websocket.send', after sending 'websocket.close'.
Моя disconnect
реализация такова
async def disconnect(self, close_code):
try:
# Leave room group
await self.channel_layer.group_discard(self.group_name, self.channel_name)
await self.log_request("disconnect")
except:
logger.exception("Failed to disconnect user from socket")
Ошибка ConnectionClosedError, которую вы видите, возникает, когда WebSocket-соединение закрывается либо клиентом, либо сервером. Аргумент close_code в методе disconnect - это код состояния WebSocket, который используется для закрытия соединения. Код состояния 1005 означает, что код состояния не был предоставлен, и обычно используется, когда соединение закрывается внезапно без надлежащего квитирования закрытия.
Ошибка RuntimeError, которую вы видите, указывает на то, что вы пытаетесь отправить сообщение websocket.send после того, как соединение WebSocket было закрыто сообщением websocket.close. Это может произойти, если вы пытаетесь отправить сообщение клиенту после того, как соединение было закрыто.
Для устранения этих проблем необходимо убедиться, что вы правильно обрабатываете WebSocket-соединение и не пытаетесь отправлять сообщения после закрытия соединения. Это можно сделать, добавив соответствующую обработку ошибок и проверяя состояние WebSocket-соединения перед отправкой сообщений.
Например, вы можете добавить проверку в метод receive, чтобы убедиться, что WebSocket-соединение все еще открыто перед отправкой сообщения:
async def receive(self, text_data):
if self.closed:
return
try:
if text_data == "healthcheck":
await self.send(
text_data=json.dumps({"type": "healthcheck", "data": self.group_name})
)
else:
logger.info(f"Unsupported WS Event: {text_data}")
pass
except:
logger.exception("Failed to handle message from client")
Вы также можете добавить проверку в метод disconnect, чтобы убедиться, что вы отправляете сообщение websocket.close только один раз:
async def disconnect(self, close_code):
if self.closed:
return
try:
# Leave room group
await self.channel_layer.group_discard(self.group_name, self.channel_name)
await self.log_request("disconnect")
except:
logger.exception("Failed to disconnect user from socket")
finally:
self.closed = True
Надеюсь, это поможет!