_long_callback_interval_1 problems

Hi @jlfsjunior,

I have the same problem with my code.

To replicate that problem:

  1. I picked code from the official documentation on page Long Callbacks | Dash for Python Documentation | Plotly, section Example 5: Progress Bar Chart Graph.
  2. I extended the code to run longer (total=1000)
  3. Set Network Throttling on Google my Chrome to “Slow 3G”

Using PyCharm I am able to set a breakpoint to the line following Why am I here?

Because my callback was triggered by _long_callback_interval_1.n_intervals component, calculations restarts. And this is exactly what I am trying to avoid.

Note - I tried to raise PreventUpdate - after detecting this unexpected callback - that didn’t help

Thanks in advance

Here is my code:

  1. requirements.txt
dash==2.2.0
dash_bootstrap_components==1.0.3
dash-core-components==2.0.0
dash-html-components==2.0.0
dash-table==5.0.0
diskcache==5.4.0
dash_tabulator==0.4.2
...
  1. I am using Python 3.9

  2. Output in the console

2022-03-10 21:14:20,758 INFO dash.py:2030 - Dash is running on http://127.0.0.1:8050/

 * Serving Flask app 'sample_long_callback' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
Optimisation.Calculate. 1 - Button Click callback.
Optimisation.Calculate. 2 - Triggers: {'prop_id': 'button_id.n_clicks', 'value': 1}
Optimisation.Calculate. 3 - Button clicked 1 times
Optimisation.Calculate. 1 - Button Click callback.
Optimisation.Calculate. 2 - Triggers: {'prop_id': '_long_callback_interval_1.n_intervals', 'value': 130}
Optimisation.Calculate. 3 - Button clicked 1 times

  1. Code
import time
import dash
from dash import html, dcc
from dash.long_callback import DiskcacheLongCallbackManager
from dash.dependencies import Input, Output
import plotly.graph_objects as go


import diskcache

cache = diskcache.Cache("./cache")
long_callback_manager = DiskcacheLongCallbackManager(cache)


def make_progress_graph(progress, total):
    progress_graph = (
        go.Figure(data=[go.Bar(x=[progress])])
        .update_xaxes(range=[0, total])
        .update_yaxes(
            showticklabels=False,
        )
        .update_layout(height=100, margin=dict(t=20, b=40))
    )
    return progress_graph


app = dash.Dash(__name__, long_callback_manager=long_callback_manager)

app.layout = html.Div(
    [
        html.Div(
            [
                html.P(id="paragraph_id", children=["Button not clicked"]),
                dcc.Graph(id="progress_bar_graph", figure=make_progress_graph(0, 10)),
            ]
        ),
        html.Button(id="button_id", children="Run Job!"),
        html.Button(id="cancel_button_id", children="Cancel Running Job!"),
    ]
)


@app.long_callback(
    output=Output("paragraph_id", "children"),
    inputs=Input("button_id", "n_clicks"),
    running=[
        (Output("button_id", "disabled"), True, False),
        (Output("cancel_button_id", "disabled"), False, True),
        (
            Output("paragraph_id", "style"),
            {"visibility": "hidden"},
            {"visibility": "visible"},
        ),
        (
            Output("progress_bar_graph", "style"),
            {"visibility": "visible"},
            {"visibility": "hidden"},
        ),
    ],
    cancel=[Input("cancel_button_id", "n_clicks")],
    progress=Output("progress_bar_graph", "figure"),
    progress_default=make_progress_graph(0, 10),
    interval=1000,
    prevent_initial_call=True,
)
def callback(set_progress, n_clicks):

    print("Optimisation.Calculate. 1 - Button Click callback.")

    ctx = dash.callback_context
    print(f"Optimisation.Calculate. 2 - Triggers: {ctx.triggered[0]}")

    print(f"Optimisation.Calculate. 3 - Button clicked {n_clicks} times")

    if str(ctx.triggered[0]["prop_id"]).startswith("_long_callback_interval"):
        # Why am I here ???
        pass

    total = 1000
    for i in range(total):
        time.sleep(0.1)
        set_progress(make_progress_graph(i, 1000))

    return [f"Clicked {n_clicks} times"]


if __name__ == "__main__":
    app.run_server(debug=True)