Consistent update dash page across connections

Hello!

I’m making a multi-page dash application that I plan to host on a server using Gunicorn and Nginx. It will access a PostgreSQL database on an external server over the network.

The data on one of the pages is obtained by a query from the database and should be updated every 30 seconds. I use to update the @callback through the dcc.Interval.

My code (simplified version):

from dash import Dash, html, dash_table, dcc, Input, Output, callback
import dash_bootstrap_components as dbc
from flask import Flask
import pandas as pd
from random import random

server = Flask(__name__)
app = Dash(__name__, server=server, suppress_callback_exceptions=True, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div([
    dcc.Interval(
            id='interval-component-time',
            interval=1000,
            n_intervals=0
        ),
    html.Br(),
    html.H6(id='time_update'),
    dcc.Interval(
            id='interval-component-table',
            interval=1/2*60000,
            n_intervals=0
        ),
    html.Br(),
    html.H6(id='table_update')
    ])

@callback(
    Output('time_update', 'children'),
    Input('interval-component-time', 'n_intervals')
)
def time_update(n_intervals):
    time_show = 30
    text = "Next update in {} sec".format(time_show - (n_intervals % 30))
    return text

@callback(
    Output('table_update', 'children'),
    Input('interval-component-table', 'n_intervals')
)
def data_update(n_intervals):
    # here in a separate file a query is made to the database and a dataframe is returned
    # now here is a simplified receipt df
    col = ["Col1", "Col2", "Col3"]
    data = [[random(), random(), random()]]
    df = pd.DataFrame(data, columns=col)
    return dash_table.DataTable(df.to_dict('records'),
                         style_cell={'text-align': 'center', 'margin-bottom': '0'},
                                style_table={'width':'500px'})

if __name__ == '__main__':
    server.run(port=5000, debug=True)

Locally, everything works fine for me, the load on the database is small, one such request loads 1 out of 8 processors by 30% for 3 seconds.

But, if you open my application in several browser windows, then the same data is displayed on two pages by two queries to the database at different times, that is, the load doubles. I am worried that when connecting more than 10 people, my server with the database will not withstand / will freeze heavily, and the database on it should work without delay and not fall.

Question: Is it possible to make page refresh the same for different connections? That is, so that the data is updated at the same time for different users and only with the help of one query to the database.

I studied everything about the callback in the documentation and did not find an answer.

Hello @giga,

Have you looked into caching the data on the web server? You can use some sort of db that is local to the computer that is a copy (table version) of the query that you are performing every 30 seconds. It sounds like a pretty hefty query to take 3 seconds.

You can either set up a process to perform the query and cache the response every 30 seconds, or on demand where the first user kicks off the timer and then the server will perform the caching query every 30 seconds from there. Instead of having a count down for the next update, you could give the last update time, taken from a timestamp of the latest cache.

Thanks for the advice! I studied page Dash Performance and added this to my code:

cache = Cache(app.server, config={
    'CACHE_TYPE': 'filesystem',
    'CACHE_DIR': 'cache-directory',
    'CACHE_THRESHOLD': 50
})

@cache.memoize(timeout=30)
def query_data():
    # here I make a query to the database and save the result in a dataframe
    return df

def dataframe():
    df = query_data()
    return df

And in the @callback function I make a call to the dataframe() function.
Everything works the way I needed it. Thank you!