Как сохранить уникальное соединение Rserve за сеанс?
Я пишу небольшое приложение Flask и подключаю его к Rserve с помощью pyRserve. Я хочу, чтобы каждый сеанс инициировал и затем поддерживал свое собственное соединение Rserve.
Что-то вроде этого:
session['my_connection'] = pyRserve.connect()
не работает, потому что объект подключения не поддерживает сериализацию в формате JSON. С другой стороны, примерно так:
flask.g.my_connection = pyRserve.connect()
не работает, потому что не сохраняется между запросами. Чтобы добавить к сложностям, не похоже, что pyRserve предоставляет какой-либо идентификатор для соединения, поэтому я не могу сохранить идентификатор соединения в сеансе и использовать его для получения правильного соединения перед каждым запросом.
Есть ли способ достичь уникального соединения для каждой сессии?
1 ответ
Следующее относится к любым глобальным данным Python, которые вы не хотите воссоздавать для каждого запроса, а не только к rserve, и не только к данным, уникальным для каждого пользователя.
Нам нужно общее местоположение, чтобы создать соединение rserve для каждого пользователя. Самый простой способ сделать это - запустить multiprocessing.Manager
как отдельный процесс.
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()
Запустите его перед запуском приложения, чтобы менеджер был доступен:
python rserve_manager.py
Мы можем получить доступ к этому менеджеру из приложения во время запросов, используя простую функцию. Это предполагает, что у вас есть значение для "user_id" в сеансе (что, например, будет делать Flask-Login). В результате соединение rserve становится уникальным для каждого пользователя, а не для сеанса.
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
Доступ к нему в представлении:
result = get_rserve().eval('3 + 5')
Это должно помочь вам начать работу, хотя есть множество вещей, которые можно улучшить, например, не жестко задавать адрес и пароль и не выбрасывать соединения с менеджером. Это было написано с Python 3, но должно работать с Python 2.