Flask + RabbitMQ + SocketIO - пересылка сообщений

Я столкнулся с проблемой при передаче сообщений от RabbitMQ пользователю через SocketIO.

У меня есть приложение Flask с интеграция SocketIO. Текущий поток пользователя выглядит как this

Проблема в том, что я не могу настроить слушателя RabbitMQ, который передает сообщения в браузер через SocketIO. Каждый раз, когда я получаю другую ошибку. В основном это закрытие соединения, или я работаю вне контекста приложения.

Я пробовал много подходов, вот мой последний.

# callback 
def mq_listen(uid):
    rabbit = RabbitMQ()
    def cb(ch, method, properties, body, mq=rabbit):
        to_return = [0]  # mutable
        message = Message.load(body)
        to_return[0] = message.get_message()

        emit('report_part', {"data": to_return[0]})

    rabbit.listen('results', callback=cb, id=uid)

# this is the page, which user reach
@blueprint.route('/report_result/<uid>', methods=['GET'])
def report_result(uid):

    thread = threading.Thread(target=mq_listen, args=(uid,))
    thread.start()

     return render_template("property/report_result.html", socket_id=uid)

где метод rabbit.listen представляет собой абстракцию, подобную:

def listen(self, queue_name, callback=None, id=None):
    if callback is not None:
        callback_function = callback
    else:
        callback_function = self.__callback
    if id is None:
        self.channel.queue_declare(queue=queue_name, durable=True)
        self.channel.basic_qos(prefetch_count=1)
        self.consumer_tag = self.channel.basic_consume(callback_function, queue=queue_name)
        self.channel.start_consuming()
    else:
        self.channel.exchange_declare(exchange=queue_name, type='direct')
        result = self.channel.queue_declare(exclusive=True)
        exchange_name = result.method.queue
        self.channel.queue_bind(exchange=queue_name, queue=exchange_name, routing_key=id)
        self.channel.basic_consume(callback_function, queue=exchange_name, no_ack=True)
        self.channel.start_consuming()

что привело к

RuntimeError: working outside of request context

Я буду рад за любой совет или пример использования.

Спасибо большое

Ответ 1

Сообщение об ошибке предполагает, что это проблема с флягой. При обработке запросов Flask устанавливает контекст, но поскольку вы используете потоки, этот контекст теряется. К тому времени, когда это необходимо, оно больше не доступно, поэтому Flask дает ошибку "работа вне контекста запроса".

Общим способом решения этого является предоставление контекста вручную. В документации есть раздел об этом: http://flask.pocoo.org/docs/1.0/appcontext/#manual-push-a-context

В вашем коде не отображается часть сокета. Но мне интересно, можно ли использовать что-то вроде flask-socketio для некоторых вещей... (https://flask-socketio.readthedocs.io/en/latest/). Я хотел бы открыть соединение RabbitMQ в фоновом режиме (предпочтительно один раз) и использовать emit функцию для отправки каких - либо обновлений для подключенных клиентов SocketIO.