Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Store large data or a service connection per Flask session

I'm writing a small Flask application and am having it connect to Rserve using pyRserve. I want every session to initiate and then maintain its own Rserve connection.

Something like this:

session['my_connection'] = pyRserve.connect()

doesn't work because the connection object is not JSON serializable. On the other hand, something like this:

flask.g.my_connection = pyRserve.connect()

doesn't work because it does not persist between requests. To add to the difficulty, it doesn't seem as though pyRserve provides any identifier for a connection, so I can't store a connection ID in the session and use that to retrieve the right connection before each request.

Is there a way to accomplish having a unique connection per session?

like image 684
alexizydorczyk Avatar asked Feb 10 '15 02:02

alexizydorczyk


People also ask

How do I store session data Flask?

The data that is required to be saved in the session is stored in a temporary directory on the server. Assign session IDs to sessions for each client. Session data is stored at the top of the cookie, and the server signs it in encrypted mode. For this encryption, the Flask application requires a defined SECRET_KEY .

Is Flask session client-side or server-side?

Flask's sessions are client-side sessions. Any data that you write to the session is written to a cookie and sent to the client to store.

Where are sessions stored in Flask?

Flask – Sessions A session with each client is assigned a Session ID. The Session data is stored on top of cookies and the server signs them cryptographically. For this encryption, a Flask application needs a defined SECRET_KEY.

How many sessions are in a Flask?

In March 2022, The CW renewed the series for a ninth and final season. As of June 29, 2022, 171 episodes of The Flash have aired, concluding the eighth season.


Video Answer


1 Answers

The following applies to any global Python data that you don't want to recreate for each request, not just rserve, and not just data that is unique to each user.

We need some common location to create an rserve connection for each user. The simplest way to do this is to run a multiprocessing.Manager as a separate process.

import atexit
from multiprocessing import Lock
from multiprocessing.managers import BaseManager
import pyRserve

connections = {}
lock = Lock()


def get_connection(user_id):
    with lock:
        if user_id not in connections:
            connections[user_id] = pyRserve.connect()

        return connections[user_id]


@atexit.register
def close_connections():
    for connection in connections.values():
        connection.close()


manager = BaseManager(('', 37844), b'password')
manager.register('get_connection', get_connection)
server = manager.get_server()
server.serve_forever()

Run it before starting your application, so that the manager will be available:

python rserve_manager.py

We can access this manager from the app during requests using a simple function. This assumes you've got a value for "user_id" in the session (which is what Flask-Login would do, for example). This ends up making the rserve connection unique per user, not per session.

from multiprocessing.managers import BaseManager
from flask import g, session

def get_rserve():
    if not hasattr(g, 'rserve'):
        manager = BaseManager(('', 37844), b'password')
        manager.register('get_connection')
        manager.connect()
        g.rserve = manager.get_connection(session['user_id'])

    return g.rserve

Access it inside a view:

result = get_rserve().eval('3 + 5')

This should get you started, although there's plenty that can be improved, such as not hard-coding the address and password, and not throwing away the connections to the manager. This was written with Python 3, but should work with Python 2.

like image 163
davidism Avatar answered Oct 20 '22 06:10

davidism