Каналы: почему сообщение отправляется в конце обработки - PullRequest
0 голосов
/ 29 мая 2020

почему используется функция syn c get_channel_layer().send(), сообщение отправляется в конце обработки

def external_send(channel_name, data):
    channel_layer = get_channel_layer()
    send_sync = async_to_sync(channel_layer.send)
    send_sync(
        channel_name,
        {
            "type": "send_json",
            "message": {"datetime": datetime.datetime.now().isoformat(), **data},
        },
    )

с использованием self.send() в работе потребителя, как ожидалось

вот мой потребитель класс для тестирования:

class TestConsumer(JsonWebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    def receive_json(self, content, **kwargs):
        logger.debug(f"RECEIVE {content}")
        self.send_json(
            {
                "id": 1,
                "text": "Before sleep: self.send_json",
                "datetime": datetime.datetime.now().isoformat(),
            }
        )
        external_send(
            self.channel_name, {"id": 2, "text": "Before sleep external_send"}
        )
        sleep(10)  # Simuleting long processing
        self.send_json(
            {
                "id": 3,
                "text": "After sleep: self.send_json",
                "datetime": datetime.datetime.now().isoformat(),
            }
        )
        super().receive_json(content, **kwargs)
        logger.debug("END")

Во внешнем интерфейсе я получаю заказ

  • {id: 1, текст: «Перед сном: self.send_ json», datetime : "2020-05-29T14: 30: 58.226545"}
  • {id: 3, текст: "После сна: self.send_ json", datetime: "2020-05-29T14: 31: 03.244865 "}
  • {id: 2, text:" Перед сном external_send ", datetime:" 2020-05-29T14: 30: 58.230164 "}

enter image description here

1 Ответ

0 голосов
/ 30 мая 2020

В ответ каждый потребитель канала получает свой маленький runl oop. Он будет обрабатывать только одно событие за раз. Этот единственный runl oop используется как для сообщений, полученных от клиента (через ws), так и для сообщений, обрабатываемых посредством событий групповой отправки на уровнях канала.

если вы receive_json спите, то есть спит l oop, так что больше ничего не произойдет. receive_json необходимо завершить sh до того, как любое сообщение, отправленное через канальный уровень, будет обработано.

Глядя на ваш код, есть несколько других моментов, на которые необходимо указать

Syn c sleep

Если вам нужно sleep в методе never делать это в методе syn c, это усыпит ваш entier python программа (все будет спать).

Используйте Asyn c потребитель, тогда вы можете await asyncio.sleep(20) это будет просто sleep ваш runl oop для этого единственного потребителя и других подключений через веб-сокеты et c продолжит работу. Это также верно для любой другой длительной задачи: вы должны использовать асинхронный c потребитель, а затем использовать asyn c threadpool для await этих длительных задач.

Вы не должны пытаться группировать отправку непосредственно к методу send_json.

Intread, вы должны создать метод на своем потребителе handle_message этот метод может вызывать send_json, и ваша группа отправляет сообщения с типом handle.message.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...