Каналы Django - websocket_disconnect вызывается в цикле - PullRequest
0 голосов
/ 28 марта 2019

Я использую Django-каналы для предоставления мгновенных уведомлений при создании нового экземпляра модели.

Для этой цели я использую django-каналы и SyncConsumer. Все работает как надо, кроме websocket_disconnect, который вызывается в цикле n раз.

Вот мой потребительский код:

class BaseConsumer(SyncConsumer):

    def websocket_connect(self, event):
        self.send({"type": "websocket.accept"})

    def websocket_receive(self, event):
        # do some stuff here

    def websocket_disconnect(self, event):
        print("websocket_disconnect")

Вот лог с моего веб-сервера:

api_1    | websocket_disconnect
api_1    | websocket_disconnect
api_1    | websocket_disconnect
api_1    | websocket_disconnect
api_1    | websocket_disconnect
api_1    | websocket_disconnect
api_1    | websocket_disconnect
api_1    | websocket_disconnect
api_1    | websocket_disconnect
api_1    | websocket_disconnect

И так будет продолжаться до тех пор, пока я не остановлю веб-сервер.

Это происходит как при закрытии вручную соединения во внешнем интерфейсе (я использую Javascript, поэтому я вызываю ws.close()), так и при закрытии вкладки браузера / клиента.

Мне это не кажется правильным, так как я слышу, как фанаты моего компьютера работают как в аду. Как я могу остановить запуск этого метода после закрытия соединения? Поскольку само соединение закрывается должным образом, как я могу убедиться в методе javascript onclose, который запускается во внешнем интерфейсе только один раз.

Кто-нибудь еще испытывал что-то подобное?

Спасибо!

1 Ответ

0 голосов
/ 28 марта 2019

У меня была эта проблема в течение нескольких дней, и только через несколько минут после публикации моего вопроса в StackOverFlow я смог найти решение своей проблемы.

Читая документацию глубже, я заметил следующее:

Когда розетка или соединение, подключенное к вашему потребителю, закрыто - Вы или клиент - скорее всего, вам отправят событие (например, http.disconnect или websocket.disconnect), и ваш экземпляру приложения будет предоставлено короткое время для это.

Как только вы завершите очистку после отключения, вам нужно поднять channel.exceptions.StopConsumer, чтобы остановить приложение ASGI чисто и пусть сервер его почистит. Если вы оставите его запущенным не поднимая это исключение - сервер достигнет своего приложения закрыть тайм-аут (который по умолчанию составляет 10 секунд в Дафни), а затем убить ваше заявление и подайте предупреждение.

Типовые потребители ниже делают это для вас, так что это необходимо только в том случае, если вы пишете свой собственный потребительский класс на основе AsyncConsumer или SyncConsumer.

(https://channels.readthedocs.io/en/latest/topics/consumers.html?highlight=websocket.disconnect#closing-consumers)

Подводя итог, чтобы правильно закрыть соединение, необходимо поднять StopConsumer.

Надеюсь, что этот ответ в будущем разрешит некоторые головные боли для других!

...