Timing out before the server does

I have a Dash application hosted on Heroku. Under some circumstances a callback will take more than 30 seconds to execute. Long callbacks are the suggested solution to this issue.

But before implementing long callbacks, it would be good to at least let the user know that the server has timed out. As described in this recent feature request, there is no way in Dash to catch the server timeout, in order to report the situation to the user.

I thought perhaps the callback could anticipate the timeout using signal.alarm(), as suggested by a post over on stackoverflow. My attempt:

import signal
import dash
import dash.dependencies as dd 

# From https://stackoverflow.com/a/25027182/2076081
class TimeoutException(Exception):   # Custom exception class
    pass
def timeout_handler(signum, frame):   # Custom signal handler
    raise TimeoutException
# Change the behavior of SIGALRM
signal.signal(signal.SIGALRM, timeout_handler)

@app.callback(
    dd.Output('results', 'data'),
    dd.Output('explanation', 'children'),
    dd.Input('parameters', 'data')
)
def _run_model_with_timeout(parameters):
    signal.alarm(30)
    try:
       results = _run_model(parameters)
    except TimeoutException:
       return dash.no_update, "Timed out"
    else:
       signal.alarm(0)   # turn off the alarm
       return results, "Run complete"

Sadly this did not work. I tried it on my local (MacOS) server, before trying on Heroku. Instead of catching the TimeoutException within the callback, the exception is raised elsewhere, and uncaught.

Is there any way a callback could learn that something takes more than 30 seconds?

hi @bridgeland
I think you can use record_timing for this.

In debug mode you can see the timings of the callbacks in the callback graph. Also, you need to add duration so call in ctx.recod_timing("callback", 1) to surpass a bug in the function