Kill dash application session after set amount of time

Hi there,

I have a web app composed of primarily Dash applications that I want to timeout after a predetermined time from first load. What I’ve understood is that I’m supposed to set flask’s permanent_session_lifetime to some timedelta, but no matter how I’ve implemented it, the interval callbacks I have in the dash apps keep firing and refreshing the data. Heres what I’m using on the app creation page.

from flask import Flask, session
from datetime import timedelta
import os
from dash_apps.demand_east.create_app import create_demand_east
from dash_apps.demand_west.create_app import create_demand_west
from dash_apps.demand_dc.create_app import create_demand_dc
from dash_apps.demand_listview.create_app import create_demand_listview
from dash_apps.home.create_app import create_home
from dash_apps.open_rfi.create_app import create_open_rfi
from dash_apps.warpwise.create_app import create_warpwise

def create_app():
    """
    Create DASH web app with same instance as flask server
    """
    server = Flask(__name__) 

    create_demand_east(server, r'queries/tot_usershare.sql', r'/dashapps/demandboard/east/')
    create_demand_dc(server, r'queries/tot_usershare.sql', r'/dashapps/demandboard/dc/')
    create_demand_west(server, r'queries/tot_usershare.sql', r'/dashapps/demandboard/west/')
    create_demand_listview(server, r'queries/locationtimer.sql', r'/dashapps/demandboard/listview/')
    create_home(server, r'/home/')
    create_open_rfi(server, r'/dashapps/openrfi/')
    create_warpwise(server, r'/dashapps/warpwise/')

    return server

server = create_app()

# config
server.config.update(
    DEBUG = True,
    SECRET_KEY = os.urandom(24)
)

@server.before_first_request
def before_request():
    session.permanent = True
    server.permanent_session_lifetime = timedelta(minutes=1)

if __name__ == '__main__':
    port = 8080
    host = '0.0.0.0'
    server.run(host=host, port=port, debug=True)

The interval components I’m using refresh every 3-5 minutes depending on the page. I thought that with the before first request decorator setting the timedelta to 1 minute, I should have expected the session to close before any refreshes occur, but they keep firing in perpetuity. What should I be doing to achieve the desired functionality?

Thanks.

Hello @bparzonz,

What are you doing to expire a session, what functionality is supposed to stop?

Right now, I’m assuming that the sessions would expire and a new one be generated. Or, it is continually updated to the next minute.

Hi @jinnyzor

The web app is currently used in our organization in many places with many simultaneous users. Sometimes users have a bad habit of leaving multiple instances of the web application open on machines that never sleep, i.e. opening the app on a machine, minimizing, and walking away. The web application is being run on a virtual machine with limited resources, and recently because of this poor behavior we have been having memory issues on the machine.

In combination with user training, I want a fallback that if an instance of the web app has been idle for a certain amount of time, flask closes the connection to conserve resources. Because the interval components register as user interaction, I figured I would just set a timeout from first load instead.

But I’ve been unable to get it to function with the code provided. What I understand from what you said is that because the page is still open in the browser, the app is simply being refreshed once the lifetime limit is reached?

Thanks

1 Like

Yes and no.

The before_request is updating your time interval to a minute from now.

This is happening on each request, including the post requests.

What I would recommend is that you have some sort of login mechanism or page that will not continuously load data or perform any tasks that would be post requests. Have a session timeout which would redirect to this page upon it being expired, you can use a redirect to this url. On the before_request, see if the session has the permanent state or is expired and redirect accordingly.

If this is in a component that is continuously performing a task, say n_intervals, you could also set a max_intervals on it to keep it from updating beyond a certain scope, and allow for the user to refresh the counter if they are still using it

But, if you want to redirect to the other page, you’ll have to use the callback to update the url.

The choice of how you accomplish this is up to you. The easiest would be to add max_intervals I think.

Thanks for the response. A couple things:

First, @app.before_first_request I believe acts differently than @app.before_request in that it should only fire after page load. When I’ve tested with a simple print() under the decorator, this seems to hold up.

Secondly, regardless of the function of the flask decorator, although navigating to another page would reduce load on the cpu due to removing the callbacks, wouldn’t the memory issue remain due to the instance of the app remaining open? Doesn’t flask create a unique instance of the application for every unique user, and allocate memory for that user upon load? What I really want is to release the reserved resources from that instance as if the user had closed the browser tab.

Thanks for your help.

Ah.

Didn’t quite catch the first there.

Anyways, with you closing the session it shouldn’t be an issue if you redirect to something that isn’t going to keep requesting from the server.

Also, I don’t think sessions or their data are stored on the server, as this would defeat the ability for multiple backends catering responses.

Id check to make sure things like printing to the application is minimized, as well as nginx logging is down to a minimum.

I do like the idea of a timeout navigation page, and Ill look into that.

My concern, though, is that the session lifetime I have set currently is less than the interval callback length (1 vs 3 minutes), so it should be terminating the session but it is not (in reality, because the session isnt based on user input, it shouldn’t matter anyway).

I’m worried this behavior will continue on the timeout page without the callbacks as well.

How can I terminate the session without closing the browser tab?

I think that the session is expiring, but possibly getting renewed upon the first request, which is the post request.

What you can do is look at the network tab and see what is happening there. Look for _dash-update-component and see what the response headers look like.

Also, for this, I’d turn off the hot reload.

One other thing, expiring the session wouldn’t keep the n_intervals from spamming the server either.

expiring the session wouldn’t keep the n_intervals from spamming the server either.

Gotcha. I’m new to web development and maybe I don’t fully understand what is incorporated into a user session. I thought killing a session was nearly the equivalent of closing a tab.

In reality, I dont really care about the data of the “session”, I just want to close the connection between the browser and the server without stopping the webserver or closing the browser tab, for the end result of freeing up the memory that flask would have allocated for that unique app instance.

Thanks for all the help :slight_smile:

I would set some max n_intervals and see if that will stop it, and keep the requests from piling up.

Either that, or redirect to the other page unless the user maintains opts to keep it going. You could reset the n_intervals too on the other max intervals as well when based upon user interaction.

@bparzonz Just a heads up that before_first_request had been deprecated and will be removed in the flask 2.3

You can find more info here:

1 Like