Greetings _jm, all,
I could make it work using the suggested method. Many thanks. For anyone having similar issue, a minimum code is shown below. Will exit the application after timeouts when the browser tab is closed. The timeouts are settable at server initialization.
However, I added a line of code to the example, which is causing some amazement. It may be due to some race condition: If having a periodic callback and the callback contains a blocking delay, the first time the callback is called, the document initialization is ran again. In my machine, if the callback period is set less than 400ms, the anomaly happens (if one runs the example code below, can perhaps see that app_init() gets called twice).
The way to avoid this is to ensure that for the first second after the document is initialized, one should not have blocking calls, I guess.
# -*- coding: utf-8 -*-
"""
Minimum for session destroy anomaly case.
Having long delay in periodic callback causes a call to cleanup_session()
which in turn runs app_init() again, but only once.
This happens only if periodic_callback is set to less than ~400ms
"""
from time import sleep
from tornado.ioloop import IOLoop
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.server.server import Server
def my_periodic_cb():
print("my_periodic_cb()")
sleep(3)
def my_cleanup_session_cb(session_context):
print("my_cleanup_session_cb()")
print("Destroyed =", session_context.destroyed)
def app_init(doc):
print("app_init()")
print("Destroyed =", doc.session_context.destroyed)
doc.on_session_destroyed(my_cleanup_session_cb)
doc.add_periodic_callback(my_periodic_cb, 100)
return doc
io_loop = IOLoop.current()
bokeh_app = Application(FunctionHandler(app_init))
server = Server({"/": bokeh_app}, io_loop=io_loop,
check_unused_sessions_milliseconds=1000,
unused_session_lifetime_milliseconds=1000)
if server._started == False:
server.start()
io_loop.add_callback(server.show, "/")
try:
io_loop.start()
except:
pass
Cheers,
Heke