Black Lives Matter. Please consider donating to Black Girls Code today.

Having Dash react to Redis messages

Hello! I am trying to have dash react to messages published by redis’s keyspace events. Essentially whenever data is changed in my redis database, redis sends out these event messages, and I want my Dash app to be listening for these, and when they occur, I want to update a part of the page. The way I’ve tried to do this is to have my app kick off a thread that looks like this:

index.py:

from app import app, pubsub, r

       ...

listener = html.Div(id='listener', style={'display': 'none'})
def subscriber():
    while True:
        message = pubsub.get_message()
        if message:
            print(message)
            listener.children=[r.get('test').decode('utf-8'),]

           ...

if __name__ == '__main__':
    check_messages = Thread(target=subscriber, daemon=True) 
    check_messages.start()
    app.run_server(debug=True, host='0.0.0.0', port=8080, use_reloader=False)

In app I create my redis connection and the pubsub.

app.py

import dash
import redis

# Dash setup
app = dash.Dash(__name__)
server = app.server
app.config['suppress_callback_exceptions'] = True

r = redis.Redis(host='localhost', port=6379)
pubsub = r.pubsub()
pubsub.psubscribe('__keyspace@0__:*')

Now this thread has no issues reading the messages when they come in. But I don’t know how to get Dash to react to them. I tried making that div called listener, and putting that in my app.layout along with a div called the data-show which would display the data whenever the listener’s children changes.

index.py:

from app import app, pubsub, r

      ...

listener = html.Div(id='listener', style={'display': 'none'})
def subscriber():
    while True:
        message = pubsub.get_message()
        if message:
            print(message)
            listener.children=[r.get('test').decode('utf-8'),]

       ...

app.layout = html.Div( 
                [
                             ...

                      html.Div(id='data-show'),
                      listener
                ]
          )

@app.callback(Output('data-show', 'children'),
              [Input('listener', 'children')])
def show_data(data):
    print(data)
    return data

This display’s the data, however when I update the data in the db, it won’t change on the page unless I refresh the page. I think this is because the callback isn’t triggered until the page is refreshed, ergo dash doesn’t care if I update the children of listener in that separate thread. How do I get dash to update the data on the page without needing a manual refresh?

1 Like