Даш длинные задачи через очередь Redis

Я хочу создать на Dash веб-приложение, которое выполняет ресурсоемкую задачу с данными, введенными пользователем, и возвращает результат в табличном формате. Во внешнем интерфейсе у меня есть обратный вызов Dash, который обновляет компоненты Dash на основе входных данных от компонентов Dash, например:

from rq import Queue
from worker import conn
import time

# redis connection to execute tasks in the background
q = Queue(connection=conn,job_timeout='3m')
@app.callback(
    [Output('table-columns', 'columns'),
     Output('table-columns', 'data'),],
    [Input('upload', 'contents'),
     Input('launch-expensive-job-button', 'n_clicks')],
     )

def expensive_task(contents, n_clicks_launch):
    df = q.enqueue(expensive_function, contents).result
    while df is None:
        time.sleep(2)
    return [{"name": i, "id": i} for i in df.columns], df.to_dict("rows")

Я использую очередь Redis для запуска задачи в фоновом режиме. Как только результат обновляется в переменной df (соглашение Redis — результат None во время обработки), я возвращаю его клиенту. Проблема в том, что моя платформа развертывания не позволяет выполнять внешние задания слишком долго. Поэтому, даже если я отправляю задание на серверную часть, мне нужно найти способ заставить приложение Dash прослушивать любые обновления переменной df.

Я уверен, что решение где-то доступно, но я слишком новичок, чтобы найти его. Рад, что мне указали на некоторую документацию, где я мог найти дорогу.


person Vlad-Marius Griguta    schedule 11.08.2020    source источник


Ответы (1)


Я думаю, вы ищете компонент Interval (документация здесь). Он запускает обновление клиента через регулярные промежутки времени, например. раз в секунду. Обратный вызов будет выглядеть следующим образом:

...
Interval(id='trigger', interval=1000)  # must be in the app layout
...

@app.callback(Output(...), [Input('trigger', 'n_intervals')])
def poll_update(n_intervals):
    # check status of redis here and update the output accordingly 
person emher    schedule 11.08.2020
comment
Спасибо за ответ, компонент Interval определенно подходит. Двигаясь дальше, не могли бы вы предложить способ заставить обратный вызов с компонентом Interval прослушивать обновления из переменной df, кроме как сделать переменную глобальной? В настоящее время я все еще обязан хранить df локально, так как это довольно большой набор данных, поэтому было бы здорово, если бы я мог передать его непосредственно в обратный вызов. Большое спасибо! - person Vlad-Marius Griguta; 15.08.2020