Dash app not refreshing in all the client browser windows

Hello,

I have run into a very weird problem. And I don’t have any clue why the application is behaving that weirdly. So I’m building an live updating dashboard using dash. The data is received is from an open endpoint https://api.misoenergy.org/MISORTWDDataBroker/DataBrokerServices.asmx?messageType=getace&returnType=json in the json format.

I have created two files one file old_data.json which stores the latest data received from the above url endpoint. The other file old_data_copy.json stores all the data point received plus the new data points. Both the files are stored in a folder named “data/” in the project directory. I basically used a callback function which hit the url every 2 seconds and if there is new data generated then i iterate over them and append them in the old_data_copy.json. In short old_data.json has most recent data from the url, and old_data_copy.json has all the data from the second we started the application.

The problem is that if i open the application in multiple browser windows, it only refreshes one instance, sometimes it doesn’t even refresh at all. I’m not even receiving any errors as well I tried waitress serve using
serve(application, host="127.0.0.1", port=8050, threads=6) still no help. I also tried Flask to run the application using application.debug = True application.run(threaded=False, processes=3)

I don’t know what is the issue.

Here is the directory structure:

application-

           assets/
                  custom.css
                  mysoaceup.wav
                  mysoacedown.wav
           data/
                  old_data.json
                  old_data_copy.json
          resources/
                  charts.py
                  get_data.py
         application.py

get_data.py → gets the data
charts.py —> return a figure object

application.py

from datetime import timedelta

import dash

from dash.dependencies import Output, Input

import dash_core_components as dcc

import dash_html_components as html

from dash_html_components.Template import Template

import plotly

import plotly.graph_objs as go

from collections import deque

import dash_auth

from dash.dependencies import Input, Output, State

from dash_bootstrap_components._components.Row import Row

from dash_core_components.Loading import Loading

import dash_html_components as html

from dash_html_components.Col import Col

from dash_html_components.Div import Div

from dash_html_components.Hr import Hr

import dash_table

import dash_core_components as dcc

import dash_html_components as html

import dash_bootstrap_components as dbc

from requests.api import get

from resources import get_data

from resources import charts

import base64

from flask import Flask

from waitress import serve

import pandas as pd

import json

import config

mysoaceup_sound_filename = "assets/mysoaceup.wav"

mysoaceup_encoded_sound = base64.b64encode(open(mysoaceup_sound_filename, "rb").read())

mysoacedown_sound_filename = "assets/mysoacedown.wav"

mysoacedown_encoded_sound = base64.b64encode(

    open(mysoacedown_sound_filename, "rb").read()

)

VALID_USERNAME_PASSWORD_PAIRS = {config.appusername: config.apppassword}

def serve_layout():

    # getting initial data from the old_data_copy()

    data, msg = get_data.filter_data()

    df = get_data.data_to_dataframe(data)

    # data = get_data.get_initial_data()

    # df = get_data.data_to_dataframe(data)

    # print(df.info())

    # getting averages

    fhr = get_data.get_fhraverage(df)

    twlv = get_data.get_12fhraverage(df)

    twntyfhr = get_data.get_24fhraverage(df)

    frtyeght = get_data.get_48hraverage(df)

    initial_trace = go.Scatter(

        x=df["instantEST"],

        y=df["value"],

        name="Scatter",

        mode="lines",

        line=dict(color="red", width=2),

    )

    scale_list = [4, 12, 24, 48]

    scale_dropdown = dcc.Dropdown(

        id="scale_selector",

        options=[{"label": i, "value": i} for i in scale_list],

        value="4",

        optionHeight=25,

        multi=False,

        clearable=True,

        persistence_type="session",

        placeholder="Hrs",

    )

    graph_card = dbc.Card(

        dcc.Graph(

            id="graph1",

            animate=True,

            # figure=fig,

            figure={

                "data": [initial_trace],

                "layout": go.Layout(

                    template="plotly_dark",

                    xaxis=dict(

                        range=[

                            min(df["instantEST"].tolist()),

                            max(df["instantEST"].tolist()),

                        ],

                        tickfont=dict(size=8),

                    ),

                    yaxis=dict(range=[-1000, 1000], tickfont=dict(size=8)),

                    margin=dict(l=0, r=1, t=0, b=0),

                    annotations=[

                        go.layout.Annotation(

                            text="4hrAvg:{} 12hrAvg:{} 24hrAvg:{} 48hrAvg:{}".format(

                                fhr, twlv, twntyfhr, frtyeght

                            ),

                            align="left",

                            showarrow=False,

                            xref="paper",

                            yref="paper",

                            x=0.5,

                            y=0,

                            bordercolor="black",

                            borderwidth=1,

                        )

                    ],

                ),

            },

            config={"displayModeBar": False},

            style={"height": "97.2vh"},

        ),

        body=False,

        color="dark",

        outline=False,

    )

    threshold_value = dcc.Input(

        id="threshold_value",

        type="text",

        placeholder="Enter Threshold Values",

        debounce=True,

    )

    app_layout = dbc.Container(

        [

            html.Div(

                [

                    dbc.Row(

                        [

                            dbc.Col(scale_dropdown, width="auto"),

                            dbc.Col(threshold_value, width="auto"),

                        ],

                    ),

                    dbc.Row(

                        dbc.Col(

                            html.Div(id="threshold-audio", style={"display": "none"})

                        ),

                    ),

                    dbc.Row(dbc.Col(graph_card)),

                    dcc.Interval(id="graph-update", interval=2 * 1000),

                    # html.Audio(id="mysoaceup", src="/assests/mysoaceup.mp3"),

                    # html.Audio(id="mysoacedown", src="/assests/mysoacedown.mp3"),

                    dcc.Interval(id="audio-update", interval=2 * 1000),

                ]

            )

        ],

        fluid=True,

    )

    return app_layout

application = Flask(__name__)

app = dash.Dash(

    __name__,

    server=application,

    suppress_callback_exceptions=True,

    external_stylesheets=[dbc.themes.DARKLY],

    update_title=None,

)


app.layout = serve_layout

@app.callback(

    [Output("graph1", "figure"), Output("threshold-audio", "children")],

    [

        Input("graph-update", "n_intervals"),

        Input("scale_selector", "value"),

        Input("threshold_value", "value"),

    ],

)

def update_graph_scatter(n, value, threshold_value):

    data, msg = get_data.filter_data() #returns the old_data_copy.json file

    data = get_data.data_to_dataframe(data)  # converts the json to dataframe

    print(value)

    value = int(value)

    # if threshold_value is not None:

    #     upper_value, lwer_value = threshold_value.split(",")

    #     print(int(upper_value), int(lwer_value))

    # else:

    #     print("No threshold value enters")

    # filtering of the data based  on selected input

    most_recent_timestamp = data["instantEST"].iloc[-1]

    # getting averages

    fhr = get_data.get_fhraverage(data)

    twlv = get_data.get_12fhraverage(data)

    twntyfhr = get_data.get_24fhraverage(data)

    frtyeght = get_data.get_48hraverage(data)

    if value == 4:

        fhrsbeforetimestamp = most_recent_timestamp - timedelta(hours=4)

        # print(fhrsbeforetimestamp, most_recent_timestamp)

        # print(fhrsbeforetimestamp in data["instantEST"].unique())

        if fhrsbeforetimestamp in data["instantEST"].unique():

            print("from 4")

            # print(data[data["instantEST"] == fhrsbeforetimestamp])

            location = data[data["instantEST"] == fhrsbeforetimestamp].index[0]

            # print(location)

            filter_data = data[location:]

            # print(filter_data["value"].mean())

            fig, msg = charts.plot_4hr_charts(

                filter_data, msg, fhr, twlv, twntyfhr, frtyeght

            )

            if msg == "new_data":

                sound_element = audio_update(msg, threshold_value)

                return fig, sound_element

            else:

                return fig, dash.no_update

        else:

            print("data not available")

            fig, msg = charts.plot_4hr_charts(data, msg, fhr, twlv, twntyfhr, frtyeght)

            print(msg)

            if msg == "new_data":

                sound_element = audio_update(msg, threshold_value)

                return fig, sound_element

            else:

                return fig, dash.no_update

    # filtering of the data for 12 hr

    elif value == 12:

        twelvehoursbeforetimestamp = most_recent_timestamp - timedelta(hours=12)

        print(twelvehoursbeforetimestamp)

        if twelvehoursbeforetimestamp in data["instantEST"].unique():

            print("from 12")

            location = data[data["instantEST"] == twelvehoursbeforetimestamp].index[0]

            filter_data = data[location:]

            print(filter_data)

            # data = data.tail(1440)

            fig, msg = charts.plot_4hr_charts(

                filter_data, msg, fhr, twlv, twntyfhr, frtyeght

            )

            if msg == "new_data":

                sound_element = audio_update(msg, threshold_value)

                return fig, sound_element

            else:

                return fig, dash.no_update

        else:

            print("data not available")

            fig, msg = charts.plot_4hr_charts(data, msg, fhr, twlv, twntyfhr, frtyeght)

            print(msg)

            if msg == "new_data":

                sound_element = audio_update(msg, threshold_value)

                return fig, sound_element

            else:

                return fig, dash.no_update

    elif value == 24:

        twntyfrhoursbeforetimestamp = most_recent_timestamp - timedelta(hours=24)

        print(twntyfrhoursbeforetimestamp)

        if twntyfrhoursbeforetimestamp in data["instantEST"].unique():

            print("from 24")

            location = data[data["instantEST"] == twntyfrhoursbeforetimestamp].index[0]

            filter_data = data[location:]

            fig, msg = charts.plot_4hr_charts(

                filter_data, msg, fhr, twlv, twntyfhr, frtyeght

            )

            if msg == "new_data":

                sound_element = audio_update(msg, threshold_value)

                return fig, sound_element

            else:

                return fig, dash.no_update

        else:

            print("data not avaiable")

            fig, msg = charts.plot_4hr_charts(data, msg, fhr, twlv, twntyfhr, frtyeght)

            print(msg)

            if msg == "new_data":

                sound_element = audio_update(msg, threshold_value)

                return fig, sound_element

            else:

                return fig, dash.no_update

    else:

        fortyeightbeforetimestamp = most_recent_timestamp - timedelta(hours=48)

        print(fortyeightbeforetimestamp)

        if fortyeightbeforetimestamp in data["instantEST"].unique():

            print("from 48")

            location = data[data["instantEST"] == fortyeightbeforetimestamp].index[0]

            filter_data = data[location:]

            fig, msg = charts.plot_4hr_charts(

                filter_data, msg, fhr, twlv, twntyfhr, frtyeght

            )

            if msg == "new_data":

                sound_element = audio_update(msg, threshold_value)

                return fig, sound_element

            else:

                return fig, dash.no_update

        else:

            print("data not avaiable")

            fig, msg = charts.plot_4hr_charts(data, msg, fhr, twlv, twntyfhr, frtyeght)

            print(msg)

            if msg == "new_data":

                sound_element = audio_update(msg, threshold_value)

                return fig, sound_element

            else:

                return fig, dash.no_update

    # getting today's date

def audio_update(msg, threshold_value):

    # data, msg = get_data.filter_data()

    # print(msg)

    if threshold_value is not None:

        upper_value, lwer_value = threshold_value.split(",")

        if msg == "new_data":

            f = open(

                "data/old_data_copy.json",

            )

            old_data_copy = json.load(f)

            f.close()

            old_data_copy_df = get_data.data_to_dataframe(old_data_copy)

            value1 = old_data_copy_df["value"].iloc[-1]

            if value1 > int(upper_value):

                return html.Audio(

                    src="data:audio/mpeg;base64,{}".format(

                        mysoaceup_encoded_sound.decode()

                    ),

                    controls=False,

                    autoPlay=True,

                )

            if value1 < int(lwer_value):

                return html.Audio(

                    src="data:audio/mpeg;base64,{}".format(

                        mysoacedown_encoded_sound.decode()

                    ),

                    controls=False,

                    autoPlay=True,

                )

    else:

        if msg == "new_data":

            f = open(

                "data/old_data.json",

            )

            old_data = json.load(f)

            f.close()

            f = open(

                "data/old_data_copy.json",

            )

            old_data_copy = json.load(f)

            f.close()

            old_data_df = get_data.data_to_dataframe(old_data)

            old_data_copy_df = get_data.data_to_dataframe(old_data_copy)

            value1 = old_data_df["value"].iloc[-1]

            value2 = old_data_copy_df["value"].iloc[-5]

            if value1 > value2:

                return html.Audio(

                    src="data:audio/mpeg;base64,{}".format(

                        mysoaceup_encoded_sound.decode()

                    ),

                    controls=False,

                    autoPlay=True,

                )

            if value1 < value2:

                return html.Audio(

                    src="data:audio/mpeg;base64,{}".format(

                        mysoacedown_encoded_sound.decode()

                    ),

                    controls=False,

                    autoPlay=True,

                )

if __name__ == "__main__":

    serve(application, host="127.0.0.1", port=8050, threads=6)

    # app.run_server(debug=True, port=8050, threaded=True, processes=4)

    # application.debug = True

    # application.run(threaded=False, processes=3)

dash version dash==1.20.0

Let me know how to do this, i don’t have any clue about this. Any help would be appreciated. I want all my users to get updated as fast as possible thankyou.

If you need any additional info let me know.