Comments (10)
@alexcjohnson Those params make a lot of sense to me. I'd also like to be able to enable retry_jitter
and retry_exponential_backoff
to avoid the situation of "Everything is retrying all at once and thus there's a windfall of requests to work through".
from dash.
Without being an expert in the inner-workings of Dash, here's my alternate suggestion in pseudocode inside the existing implementation, noted with JKUNSTLE NOTE
.
def _make_job_fn(fn, celery_app, progress, key):
cache = celery_app.backend
# JKUNSTLE NOTE: added bind=True, add `self` param to function
@celery_app.task(name=f"long_callback_{key}", bind=True)
def job_fn(self, result_key, progress_key, user_callback_args, context=None):
def _set_progress(progress_value):
if not isinstance(progress_value, (list, tuple)):
progress_value = [progress_value]
cache.set(progress_key, json.dumps(progress_value, cls=PlotlyJSONEncoder))
maybe_progress = [_set_progress] if progress else []
ctx = copy_context()
def run():
c = AttributeDict(**context)
c.ignore_register_page = False
context_value.set(c)
try:
if isinstance(user_callback_args, dict):
user_callback_output = fn(*maybe_progress, **user_callback_args)
elif isinstance(user_callback_args, (list, tuple)):
user_callback_output = fn(*maybe_progress, *user_callback_args)
else:
user_callback_output = fn(*maybe_progress, user_callback_args)
except PreventUpdate:
# Put NoUpdate dict directly to avoid circular imports.
cache.set(
result_key,
json.dumps(
{"_dash_no_update": "_dash_no_update"}, cls=PlotlyJSONEncoder
),
)
# JKUNSTLE NOTE: catches user-raised retry exception so
# Dash can control parameterization api.
except RetryBGTask as e:
# JKUNSTLE NOTE: retry in 1 second.
# should optionally be configured by e.args parameters, passed up from user function.
self.retry(countdown=1)
except Exception as err: # pylint: disable=broad-except
cache.set(
result_key,
json.dumps(
{
"long_callback_error": {
"msg": str(err),
"tb": traceback.format_exc(),
}
},
),
)
else:
cache.set(
result_key, json.dumps(user_callback_output, cls=PlotlyJSONEncoder)
)
ctx.run(run)
return job_fn
from dash.
@T4rk1n You've helped me with a feature request before- hoping to bump for some help!
from dash.
I think retrying callbacks (normal callbacks too) could be a good feature addition.
The API, I think it could have the arguments be in callback arguments and I also like the args in the error so something like.
from dash import RetryCallback
class CustomError(Exception):
pass
@callback(
...,
retry=True, # Global retry all errors.
retry_after=360, # Global retry after argument
retry_on_error=[CustomError, RetryCallback], # Retry only on those errors.
)
def cb(*args):
raise RetryCallback(after=1) # Custom retry after argument.
For the implementation I think we could catch the exceptions in dispatch and use the renderer to resend the same callback in a timeout. Can catch directly for normal callbacks and bg response has key in the response dict "long_callback_error"
that is currently re-raised as LongCallbackError
, would need to add more info to reconstitute the error for the retry_on_error
.
cc @alexcjohnson @Coding-with-Adam
from dash.
I like it! I might change retry_after
and after
to retry_delay
and delay
to be a little more specific ("after" could be an event instead of a time, or could even be taken as "retry after these errors")
Two other pieces come to mind you might want with this:
max_tries
- might default to something like 5 so this doesn't kick off an infinite loop if the error isn't really transient, but we could supportNone
or some such if you want to allow an infinite loop.- Some way to report on retry status. Maybe
retry_status=Output('my_div', 'children')
, and by default we construct a string likeattempt #1 failed with CustomError, trying again
but you can provide your own message likeraise RetryCallback(status=f"Oops, the database was locked on attempt #{ctx.retry_num}, we'll try again in 2 minutes")
orstatus=dcc.Markdown(...)
or whatever.
from dash.
@alexcjohnson @T4rk1n What's the typical timeline on a feature request like this for ya'll? (Not meant in a demanding tone, just curious so I can set objectives based on your timeline)
from dash.
Related Issues (20)
- [Help] how to add a contentChange listener on html.Div components HOT 1
- [BUG] HOT 1
- [BUG] dcc.Input selectionStart not functioning as expected
- [Feature Request] Add date support for dcc.Slider/dcc.RangeSlider
- [BUG] use Patch to append children,but init ui disappear HOT 2
- [BUG] callback in infinite loop but only triggered once HOT 4
- Selenium 4.2.0 Version Vulnerability
- [Feature Request] Render table can add Grand Total HOT 1
- Decouple Dash & Celery HOT 1
- [Feature Request] Get current active / clicked shape from plotly figure HOT 2
- Validate url to prevent XSS attacks HOT 4
- [MAINTENANCE] Improve react-docgen usage
- [BUG] dcc.Dropdown value does not update when an option is removed (regression from #1868)
- [Feature Request] Python 3.12 support HOT 1
- [Feature Request] Send categorical color data on click/hover/select HOT 4
- [Feature Request] Virtual WebGL support HOT 2
- [BUG] `dcc.Graph` inserts phantom rectangular shape on callback update seemingly randomly HOT 2
- [Feature Request] `dash.callback` should utilize `functools.wraps` HOT 4
- Dangerous link detected Error in Dash Debug Window after upgrading from 2.14.2 to 2.15.0 HOT 17
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dash.