Use original session/document on page reload

I’m creating a web application using Bokeh. My application allows users to retrieve data from a database and perform minor transformations on the data in addition to visualizing the data.
One issue that I’ve come across is that if the browser page is reloaded, then a new session is started and the user loses all the work that was performed. Is there a way to prevent this?

I have a main.py module that contains all the bokeh code, essentially:

from bokeh.io import curdoc

doc = curdoc()

# Create UI elements and layout
# ...

doc.add_root(layout)

And I start the server from my python environment:

>> bokeh serve --show main.py

It appears to me that on reload of the webpage, bokeh does not use the same session/document, but drops the websocket connection, connects a new websocket and creates a new session and document. The bokeh server is still using the same Python process, so I suspect the original session/document may still exist (unless there are no longer any references).

Is there a way to maintain a websocket connection or use an existing session/document if the webpage is (accidentally) reloaded, or even prevent the page from reloading?

Or perhaps I’m implementing this application incorrectly?

If your users are connecting directly to the bokeh server then there is not much that can be done that I can think of.

New connections without ?bokeh-session-id={session_id} will always generate a new session. Your users could manually add ?bokeh-session-id={session_id} to reconnect to an existing session (assuming it has not timed out and been deleted) but that’s probably not a very good UX, even if you added explicit instructions containing the correct session id if to the page.

OTOH if you are embedding the app in a page, then you could potentially exert more control by employing pull_session on the first load to generate a session, and save off that session id. Then using server_session with that session id to have the page connect to that specific session. See, e.g.

Edit: just being clear, that example always creates a new session by calling pull_session. You’d want to modify things so that pull_session only gets called on a first load, in whatever way is most suited for your situation.

Of course, you may need to tinker with session expiration timeouts or even disable them entirely, The above will not work if the session is already gone. So you probably need to have your page template do a something like a reload to a “bare” URL to create a new session, in case there is any error on load.

@Bryan, thanks for your response! This looks like it could be promising.
I’m not familiar with Flask or HTML, and I’m new to Bokeh. What ways are there to only pull_session on first load?

Actual web-dev is not my area of expertise, unfortunately. I am pretty certain there are ways to do this, but I don’t have any first-hand knowledge to share. At a minimum, I can state that you will need to store off the session ID somewhere for future use.

If you will only ever have a single user, then I suppose you could just store it off in a global var and the existence of a non-None value for it could signal that the existing session with that ID should be re-used.

But assuming you’ll have multiple users, you’d need to map the incoming request to a “user” (in a loose general sense) and then use that information to store and then later look up the correct ID to re-use.

Edit: Also just to note, the example used Flask because it’s a common choice and easy to set up. But you are by no means limited to it if there are other web server tools you prefer (e.g. Django, Tornado, celery, whatever)