Panel server for multiple users

@nghenzi , @Marc Thank you so much for your help and support
Excellent. I see that there are a lot of discussions on the topic of multiprocessing, multithreading and asynchrony in panel. I’m a bit new to this. Therefore, it is difficult for me to understand which direction to go. But I would really like to understand how it works and how to do it correctly. Plus - it will help the panel, holoviews and bokeh community as there is clearly not enough documentation. So I will formulate my task clearly and I think that data researchers who want to use panel in their work will sooner or later have this task:
I want to run a panel server to display some dynamic graphs based on holoviews and bokeh. at the same time, the user can change some parameters (sliders, for example) and the graph should be rebuilt. Rebuilding a graph can be a computationally expensive task (I think it’s important when there is a choice between multithreading and parallelism in python). Moreover, I would like the application to be multi-user. That is, when one user changes something in the schedule, it should not affect the work with the schedule of another user in any way.
The task is understandable in principle, because most often servers are deployed for this. So, let’s try to figure out how to do this, maybe update the documentation and help users.

A simple example with the sine function that was described above is enough. Instead of the sine function, there can be any holoviews object. So, how to make sure that this function does not block the server for a large number of users? Where should I start?

1 Like

HI again,

after thinking a little about the user interface, if you have a graph which has to be updated with a expensive task, you can only trigger this task once. Then the sliders, or any widget which changes often can not trigger this task. Then the example with the button it should do the task. The app should be inside a function.

import panel as pn, numpy as np
import holoviews as hv, pandas as pd
import asyncio
import time

from threading import Thread # Asyncio
from functools import partial
from holoviews.streams import Pipe, Buffer

pn.extension()
pn.config.sizing_mode = 'stretch_width'
hv.extension('bokeh')

# Example df for buffer
df = pd.DataFrame({"x":np.array([]),
                   "y":np.array([]),
                   "z":np.array([])}).set_index("x")

# Buffer that updates plot
buffer = Buffer(data=df)

# Some example scatter plot
dmap = hv.DynamicMap(hv.Scatter, 
                     streams=[buffer]).opts(bgcolor='black', 
                                            color='z', 
                                            show_legend=False, 
                                            width = 1200, height = 800,responsive=False
                                           )


@asyncio.coroutine
def update(x,y,z):
    buffer.send(pd.DataFrame({"x":x,"y":y,"z":z}).set_index("x"))
 

def blocking_task(doc):
     time.sleep(5)
     x = np.random.rand(1)
     y = np.random.rand(1)
     z = np.random.rand(1)
        # update the document from callback
     if doc:
          doc.add_next_tick_callback(partial(update,x=x,y=y,z=z))
     
    
def button_click(event):
    thread = Thread(target=partial(blocking_task, doc=pn.state.curdoc))
    thread.start()
    
    
btn = pn.widgets.Button(name='Run')    
btn.on_click(button_click)
    
    
p1 = pn.Column(btn, 
               pn.Row(dmap,  width = 1200, height = 800, sizing_mode="fixed")
              )    
p1.show('streaming hv')