Create 'Application' on the fly from the client side

Hi,

I don’t think this is possible, but it seems to me to be a useful feature.

Consider the case where we have a data stream, say weather data from a collection of sensors. The sensors are by location, so the data stream looks like:

(LONDON, 13.6)

(LONDON, 14.6)

(PARIS, 15.6)

(LONDON, 13.2)

Every time I see a new city, I’d like to create a new Bokeh application. One way to do this would be to use ‘bokeh serve’ to serve up a directory with one script per city - then I’d have the endpoints “/london”, “/paris” etc However, this is impractical if I don’t know how many cities I might be seeing in advance.

There are two possible improvements that might help.

  1. ‘Server side’ implementation

When a script is loaded using ‘bokeh serve’, that script could hook the bokeh.Server object and be able to add Applications (aka app_path) on the fly. It doesn’t appear this is currently possible, as the scripts are already considered applications, and have access to a limited API (namely ServerContext and SessionContext).

  1. ‘Client side’ implementation

It seems to me the best solution is to allow bokeh.client.push_session to specify a brand new app_path. Continuing the above example, pseudo code might look like:

city = LONDON                                            # comes from data stream

if city not in city_dict:                                # if we have not seen the city before

    document = Document()                                # TODO: populate the Document

    update_document(document)                            # Update the document with the latest data

    session = push_session(document, app_path='/'+city)  # We now have a new server endpoint: '/LONDON'

else:

    session = city_dict[city]                            # we've seen this city before: we already have a session

    update_document(session.document)                    # Update the document with the latest data

In practice, create applications on the fly would probably need a separate api (although the above could be a short-cut for a common case), something like:

ClientServerContext:

 GetApplications()             # Get a list of application instances

 CreateApplication(app_path)   # Create a new application, served at the given app_path

 GetApplication(app_path)      # Get the application served on the given app_path

I’m going to take a look at hacking up bokeh.Server to see if I can’t get something working, and will post my learnings.

Regards,

Josh.

···

Hi Josh,

This does seem like a pretty useful idea. It's definitely true that some new features in this direction would probably make it possible to make Bokeh apps that are a bit more sophisticated, without having to resort to a separate Flask or Django server and embedding from Bokeh server. For instance, I am about to add support for a custom Jinja template, which should basically enable any "single page application" to be completely served directly from a Bokeh server, if that's desired.

For something more sophisticated like what you are proposing with multiple endpoints, I think the concern is not to go too far down the rabbit hole. However, I think it might be possible to expose some hooks that expose more of Tornado, and let user's serve their own needs (i.e. dig their own rabbit holes). Summarizing my off-the-cuff thoughts, I see two possibilities:

* Add API to allow Bokeh apps or clients to install new Bokeh apps

This is what you've suggested, and certainly a possibility. Maybe not that hard to do either, but worth thinking about implications and concerns.

* Map a class of endpoints to an app, and expose the specific URL/endpoint as an argument

So this approach is not about making and installing *new* apps, it's about getting the "/LONDON" part of the URL to one existing app, so it can do something different based on that information, than if the user navigates to "/AUSTIN"

I think my personal inclination would be to look at the second option first. It's less "modular" in the sense that one app is responsible for switching on routes internally, but it seems a little but less disruptive to the current model, and also has no new API (but possibly new configuration spellings). But I'd be curious what other folks think.

Thanks,

Bryan

···

On Mar 17, 2016, at 9:52 PM, [email protected] wrote:

Hi,

I don't think this is possible, but it seems to me to be a useful feature.

Consider the case where we have a data stream, say weather data from a collection of sensors. The sensors are by location, so the data stream looks like:

(LONDON, 13.6)
(LONDON, 14.6)
(PARIS, 15.6)
(LONDON, 13.2)

Every time I see a new city, I'd like to create a new Bokeh application. One way to do this would be to use 'bokeh serve' to serve up a directory with one script per city - then I'd have the endpoints "/london", "/paris" etc However, this is impractical if I don't know how many cities I might be seeing in advance.

There are two possible improvements that might help.

1. 'Server side' implementation
When a script is loaded using 'bokeh serve', that script could hook the bokeh.Server object and be able to add Applications (aka app_path) on the fly. It doesn't appear this is currently possible, as the scripts are already considered applications, and have access to a limited API (namely ServerContext and SessionContext).

2. 'Client side' implementation
It seems to me the best solution is to allow bokeh.client.push_session to specify a brand new app_path. Continuing the above example, pseudo code might look like:

    city = LONDON # comes from data stream
    if city not in city_dict: # if we have not seen the city before
        document = Document() # TODO: populate the Document
        update_document(document) # Update the document with the latest data
        session = push_session(document, app_path='/'+city) # We now have a new server endpoint: '/LONDON'
    else:
        session = city_dict[city] # we've seen this city before: we already have a session
        update_document(session.document) # Update the document with the latest data
            
In practice, create applications on the fly would probably need a separate api (although the above could be a short-cut for a common case), something like:
    
    ClientServerContext:
     GetApplications() # Get a list of application instances
     CreateApplication(app_path) # Create a new application, served at the given app_path
     GetApplication(app_path) # Get the application served on the given app_path

I'm going to take a look at hacking up bokeh.Server to see if I can't get something working, and will post my learnings.

Regards,

Josh.
     
--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/944f86cc-9e7a-4ed8-94a4-f4910d9e8f8f%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.