-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
[BUG] state change for long_callback can cause infinite loop #2132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Oh interesting - |
I think it is fixed, before it was triggered by the interval callback which would collect the current state and generate the cache key on that callback. Job ids/cache keys are now saved on the renderer store so it wouldn't change the job_id on state changes. On input change it match the old ids and cancel the old jobs. |
OK great - let's leave this issue open for the moment then, and when we have a new release (very soon!) @kwikwag perhaps you can retest and see if it is indeed fixed? |
Will do |
It seems to work well now, thanks for the fix! P.S. I modified the above code to work slightly clearer by adding @app.callback(
background=True,
output=Output('data', 'children'),
inputs=[Input('button', 'n_clicks')],
state=[State('data', 'children')]
)
def clicked(n_clicks, data):
if n_clicks is None:
return json.dumps(dict(data=0, n_clicks=n_clicks))
state = json.loads(data)
return json.dumps(dict(data=state['data'] + 1, n_clicks=n_clicks)) |
Thank you so much for developing Dash!
pip list | grep dash
Describe the bug
Consider the following setup:
Every time the user clicks the button, the callback will be called once and count will increase. Note that
state
andoutput
point to the same variable.However, if you replace
@app.callback()
with@app.long_callback()
you will get an infinite loop. The reason for this is thatDash.long_callback()
uses the input arguments -- including the 'state' arguments -- to create a unique key to identify the pending job. When the state changes, this key changes, and the job gets resubmitted.The above is similar but not quite my use-case: I have a long-running multi-part job. I want the first part to be calculated only once, i.e. when the user first clicks the button, but not re-calculated every time the button is hit. For this reason I share 'state' and 'output' - the result of the first calculation gets cached in a store. In my case, the result of the first calculation doesn't change upon re-invoking the job, so the callback gets invoked exactly twice.
Expected behavior
@app.long_callback()
should behave the same as@app.callback()
, specifically, invocations due to 'state' changes should be avoided as they are not 'inputs' changes.Screenshots
The text was updated successfully, but these errors were encountered: