The main motivating use-case behind Bokeh was just simple one-off callbacks for a retained-mode document, ala Shiny. So while this kind of usage is possible in principle, in practice it definitely pushes the boundaries of what is typical for Bokeh, and what is regularly exercised and tested. I could try to make a very quick investigation to see if any specific observations or suggestions come to mind. But I would absolutely need something I could just copy and paste and run, i.e. a complete Minimal Reproducible Example
FWIW I was able to find a workaround by adding both callbacks to the original event. The drawback is I can’t pass data from the first callback to the second, requiring a global variable:
run_data = []
idx = 0
def on_button_click():
run_current_button.disabled=True
if(look_for_run()):
info_text.text = 'Run exists'
run_current_button.disabled = False
return
info_text.text = 'Run submitted'
run_current_button.disabled = False #Allows user to queue more runs while waiting
idx = idx + 1
curdoc().add_next_tick_callback(partial(run_current, index=idx))
curdoc().add_next_tick_callback(partial(after_run, index=idx))
@without_document_lock
async def run_current(index):
# Call run and await results
run_data[index] = await submitRun(model_location, run_name, inputs)
async def after_run(index):
data = run_data[index]
table_data_source.stream(data)
info_text.text = 'Run complete, see table'
....
button = Button(label='Run current values')
button.on_click(on_button_click)