What happens when you have a blocking task?

Hi Bokeh Dev team,

First time user here. I just wanted to say great library! I’ve done a lot of MATLAB GUI and Python pyqt in the past and I’ve always had problems with helping non SWE setup their environment. I don’t have lot of webdev experience, so Bokeh solves my problem! For context, I’m developing a bokeh app for non SW engineers to do data analysis. So I’m expecting 1 - 10 users for now, but if this successful, it could be up to 20 or 30 users. I am currently running bokeh serve w/ num_proc = 8 to handle the load, but I haven’t really tested more than 2 users yet.

Some of my code requires a blocking task (Parsing raw data) that could take 10s of seconds. I was wondering what are the negative effects of having a blocking task? I tried searching around and I couldn’t find anything besides don’t do it and make sure to add_next_tick_callback (Running a Bokeh server — Bokeh 2.4.2 Documentation).

So I was wondering, what’s the worst thing that could happen, how can I verify that this is indeed happening, and then I’d like to verify that I did fix the problem. I’m assuming I can cause bad behavior if I have two users connected to a single process and try to do stuff during a blocking task. If one user starts a blocking task, is the only thing that happens is that the second user can’t interact w/ their session any more? Is there anything else I need to know?

edit: Also I forgot to ask a couple more questions:

  1. Is the event loop running at some periodic rate
  2. In the linked example, do I always need this decorator when calling a callback with add_next_tick_callback?
    @gen.coroutine
    def update(x, y):
    source.stream(dict(x=, y=[y]))

Thanks all!

If you do blocking work in a Bokeh callback then any other clients will “freeze” until that work is done, with events piling up in the mean time. I suppose its possible that events could even back up until some further problems occur, but typically they would just trigger as usual once the process is unblocked.

If you want to do blocking work the best advice is to put it in a thread that adds a “next tick” callback at the end to perform any updates base on the work in the thread. It is important that any updates to Bokeh models (e.g. a ColumndDataSource) happen in the “next tick” callback, and not directly in the thread. There are complete examples of you can refer to in the Users Guide section Updating From Threads

If you are using Bokeh 2.x and Python 3, you can use native coroutines, i.e. async def, instead of the gen.coroutine decorator.


Some day I’d really like to simplify things and remove the locking on Bokeh callbacks and just allow for e.g. awaiting a thread executor, but I’m not sure offhand when that might happen. It’s possible this might even work now with the without_document_lock decorator but I have not tried.

1 Like

Great, thanks for confirming what I thought originally! Unfortunately, my company is still stuck on python 3.5, so I’m stuck on bokeh 1.4.0 for now.

hey Bryan, finally had some time to try this stuff out. Just wanted to drop a comment and say I’m impressed with how easy it is to manage locking / unlocking callbacks :). Nice job!

1 Like