1 sec refresh Interval for a 5 sec task

If there is a callback that is triggered every 1 second with the Interval component, but the callback function has an execution time of say 5 seconds, will dash app choke and get stuck? I want to understand what could be happening in the background in this case.

layout = html.Div(children = [
html.P(id = ‘update_p’),
dcc.Interval(id = ‘refresh’, interval=1*1000, n_intervals=0),
])

@app.callback(
Output(‘update_p’,‘children’),
Input(‘refresh’,‘n_intervals’)
)
def update(n_intervals):
time.sleep(5)
return n_intervals

Thanks

1 Like

working sample code

import time
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

app = dash.Dash(__name__)


app.layout = html.Div(
    [
        html.P(id="update_p"),
        dcc.Interval(id="refresh", interval=1 * 1000, n_intervals=0),
    ]
)


@app.callback(Output("update_p", "children"), [Input("refresh", "n_intervals")])
def update(n_intervals):
    time.sleep(5)
    print("sleeped")
    return n_intervals


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

@noman dash will handle that with the queue

@byronz thanks so much for the input!

Hi, I am using your code to see how dash.Interval really works. I can see that the calls from Interval component are queued up like you showed in the gif, but the layout is not updated with n_intervals number. However, if I reduce the sleep time to 0.5 seconds in which case the interval time (1s) is enough for the function to terminate, the html.P component can be updated by n_interval:

It seems to me that the output components will stop updating if the callback function is ‘cutoff’ by another call from Interval. I am wondering if we have a solution to this issue, or at least throw some exceptions telling me that it is terminated immaturely.

I’m having the same issue, where I’m triggering a callback once per second, but they seem to be piling up in the browser and eventually crashing the app. Two questions:

  1. how can I effectively delay the start of the interval callback until the page that finished its initial load of the layout (most of the piling up happens at initial page load)
  2. I ideally want the callback to fire once per second, (the callback usually runs in a few hundred milliseconds so this should be possible, but it sometimes takes longer). Can I make sure that the next instance doesn’t trigger until the previous one has finished somehow?
1 Like

I guess the simplest approach would be to create an is-running flag serverside (in a file, a memory cache, anything). You then set it to true before starting the task and false afterwards. And before starting the task, you check if it’s already running; if it is, raise a PreventUpdate exception.

That general approach sounds reasonable, but wouldn’t I want that state flag to exist on the client side, not the server side? The pile-up seems to be happening on the client. If so, does dash have some easy built-in mechanism for writing/reading a session variable that would enable this?

If your callback is clientside, the flag should reside clientside. If your callback is serverside (i.e. normal callbacks written in python), the flag should be serverside (unless you make a callback chain with a client-side flag; that’s also an option). There have been some changes to the callback logic in Dash though, so i am not sure if the “first” callback will ever return, if subsequent callbacks are dispatched. If it doesn’t, your’ll need to store the result somewhere (e.g. in a file of memory cache) and read it in the subsequent callback.

Hi @Emil, I have a similar situation where I have a 4 second interval triggering a callback that generally takes 2 seconds but sometimes because of network latency the requests get piled up. I understand the simplest approach is to “create an is-running flag serverside”. I’ve been trying to think/implement a way of doing this through call backs alone with the is_running_flag held in a dcc.store object, but because callbacks are synchronous, I think I would need to implement an asynchronous semaphore type solution like the following:

Before I start implementing this, I wanted to confirm that’s the type of asynchronous solution you meant or if there is another simpler way?

I think it would be much simpler with a server side flag. Alternatively you could check out this thread,

Agree, it would be simpler, but how can that be done? Currently, I have a 4 second interval that is an input to trigger the callback, but if intervals pile up then they will also trigger the callback even if the prior interval call back is still running. I can add an is_running_flag in the callback output and at the end of the callback this is_running_flag can be set to False to signal the process is complete, but what is the mechanism at the start or between the Interval firing to the Callback being triggered that can set the is_running_flag to True, so if there is a pile up and the prior interval process is still running when the next interval triggers the callback, then a prevent update exception can be raised?