Store large data or a service connection per Flask session

前端 未结 1 1068
盖世英雄少女心
盖世英雄少女心 2020-11-21 11:32

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.

相关标签:
1条回答
  • 2020-11-21 11:54

    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.

    0 讨论(0)
提交回复
热议问题