Handling Concurrent User Sessions in a Panel Application with Basic Authentication

Hello,

I am developing a web application using Panel and I’ve encountered an issue with handling concurrent user sessions. The application is designed to process and display data uniquely for each user session. However, I’ve noticed that the actions and queries of one user seem to affect the response time of another user’s session. This issue becomes more pronounced with an increasing number of users.

The application includes a Dashboard class, which is instantiated for each user session. Despite this, there seems to be some unintended shared state or resource contention between sessions.

Here’s a brief overview of the application’s structure:

  • The Dashboard class in dashboard_v1.py handles the user interface and data processing.
  • Class-level variables like Dashboard._lock are used for some operations.
  • There are several module-level variables for configuration and utility functions.
  • The application uses asynchronous methods for data fetching and processing.

Example Scenario:

To illustrate the issue, consider a scenario with two users, User1 and User2, both using the application simultaneously. Suppose User1 performs an action that triggers a data processing task expected to complete in 10 seconds. Almost concurrently, User2 performs a different action that initiates a more resource-intensive task expected to take 50 seconds. Ideally, User1 should receive their results in about 10 seconds. However, in practice, both User1 and User2 receive their results after 50 seconds, indicating that User1’s session is seemingly waiting for User2’s task to complete.

This simultaneous use case raises concerns about scalability and user experience, especially as the number of concurrent users increases. My goal is to ensure that each user’s session operates independently without being affected by the load or processing time of other sessions.

I’m seeking advice on the best practices to ensure each user session in a Panel application is completely isolated and does not interfere with other sessions. Specifically, I’m looking to understand:

  1. How to effectively manage state and data in a way that is specific to each user session.
  2. Strategies to avoid any shared state or resource contention between sessions in a Panel application.
  3. Best practices for using asynchronous operations within Panel and ensuring they don’t negatively impact the concurrency of the application.

I’m including the relevant portions of my code for reference and will provide more details if needed. Any insights or suggestions on how to resolve this issue would be greatly appreciated.

import logging
import panel as pn
from src.dashboard_v1 import Dashboard
from dotenv import load_dotenv
import os


load_dotenv()

app_url = os.getenv("APP_URL")
port = int(os.getenv("PORT"))
cookie_secret = os.getenv("COOKIE_SECRET")

user_credentials_str = os.getenv("CREDENTIALS")
user_credentials = dict(cred.split(":") for cred in user_credentials_str.split(","))


logging.basicConfig(level=logging.INFO)


def createApp():
    try:
        panelApp = Dashboard()
        return panelApp.servable()
    except RuntimeError as e:
        logging.error(f"Encountered a RuntimeError: {e}")
        return pn.pane.Markdown("A RuntimeError occurred. Please try again later.")
    except Exception as e:
        logging.error(f"Unhandled exception: {e}")
        return pn.pane.Markdown("An unexpected error occurred. Please try again later.")


pn.serve(
    createApp,
    port=port,
    address=app_url,
    allow_websocket_origin=["*"],
    basic_auth=user_credentials,
    cookie_secret=cookie_secret,
    show=False,
)

Thank you!

Hi,

I would recommend you take a look at that page in the docs: Add concurrent processing — Panel v1.3.2

In my situation I usually enable automatic threading.

As for compartmentalisation between users, maybe try creating your server from the command line instead of using pn.serve?

1 Like