Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bokeh Session and Document Polling

I am trying to serve bokeh documents via Django using the bokeh-server executable, which creates a Tornado instance. The bokeh documents can be accessed via URL provided by the Session.object_link method. When navigated to, the bokeh-server executable writes this to the stdout (IP addresses have been replaced with ellipses):

INFO:tornado.access:200 POST /bokeh/bb/71cee48b-5122-4275-bd4f-d137ea1374e5/gc (...) 222.55ms
INFO:tornado.access:200 GET /bokeh/bb/71cee48b-5122-4275-bd4f-d137ea1374e5/ (...) 110.15ms
INFO:tornado.access:200 POST /bokeh/bb/71cee48b-5122-4275-bd4f-d137ea1374e5/gc (...) 232.66ms
INFO:tornado.access:200 GET /bokeh/bb/71cee48b-5122-4275-bd4f-d137ea1374e5/ (...) 114.16ms

This appears to be communication between the python instance running the Django WSGI app (initialized by Apache running mod_wsgi) and the bokeh-server executable.

When the browser is sent the response, including the graphs and data etc. required for the bokeh interface, there is some initial networking to the browser, followed by networking if there is any interaction with the graphs which have python callbacks. When the user closes the window or browser, the same networking above continues. Moreover, the networking only stops when the Django or bokeh-server processes are killed.

In order to start a bokeh session and pass a URL back to the Django template, it is necessary to start the bokeh session in a new thread:

def get_bokeh_url(self, context):
        t = Thread(target=self.run)
        t.start()

        return self.session.object_link(self.document.context) 

def run(self):
    return self.session.poll_document(self.document)

self.session and self.document were both initialized before the thread was started. So at the point where get_bokeh_url is called, there are some graphs on the document, some of which have interaction callbacks and session has been created but not polled via poll_document (which appears necessary for interaction).

The thread keeps running forever unless you kill either Django or bokeh-server. This means that when more requests come through, more threads build up and the amount of networking increases.

My question is, is there a way to kill the thread once the document is no longer being viewed in a browser?

One answer that I have been pondering would be to send a quick request to the server when the browser closes and somehow kill the thread for that document. I've tried deleting the documents from the bokeh interface, but this has no effect.

like image 225
luke Avatar asked Mar 16 '15 12:03

luke


1 Answers

The bokeh server periodically checks whether there are connections to a session. If there have been no connections for some time, the session is expired and destroyed.

As of version 0.12.1, the check interval and maximum connectionless time default to 17 and 60 seconds, respectively. You can override them by running the server like this

bokeh serve --check-unused-sessions 1000 --unused-session-lifetime 1000 app.py

This is rather hard to find in the docs, it's described in the CLI documentation and in the developer guide, in a section on Applications, Sessions and Connections in the Server Architecture chapter. There's also a closed Github issue on this topic: Periodic callbacks continue after tabs are closed #3770

If you need custom logic whenever a session is destroyed, use the directory deploy format for your app and add a server_lifecycle.py file containing your Lifecycle Hooks, specifically this one:

def on_session_destroyed(session_context):
    ''' If present, this function is called when a session is closed. '''
    pass
like image 93
cw' Avatar answered Sep 30 '22 00:09

cw'