Как создать сеанс базы данных SQLAlchemy для каждого запроса - PullRequest
0 голосов
/ 10 января 2019

У меня есть приложение с несколькими арендаторами Python Falcon. У каждого арендатора есть своя база данных. При входящем запросе мне нужно подключиться к базе данных клиентов.

Но здесь есть ситуация. Конфиги базы данных хранятся в другом сервисе, и конфиги регулярно меняются.

Я пытался создать сеанс перед процессом. Но sql запросы замедляются после этого изменения. Чтобы сделать это быстрее, что мне делать? Постскриптум : Я использую PostgreSQL

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
import config
import json
import requests
class DatabaseMiddleware:
    def __init__(self):
        pass
    def process_resource(self, req, resp, resource, params):
        engineConfig = requests.get('http://database:10003/v1/databases?loadOnly=config&appId=06535108-111a-11e9-ab14-d663bd873d93').text
        engineConfig = json.loads(engineConfig)
        engine = create_engine(
            '{dms}://{user}:{password}@{host}:{port}/{dbName}'.format(
            dms= engineConfig[0]['config']['dms'],
            user= engineConfig[0]['config']['user'],
            password= engineConfig[0]['config']['password'],
            host= engineConfig[0]['config']['host'],
            port= engineConfig[0]['config']['port'],
            dbName= engineConfig[0]['config']['dbName']
        ))
        session_factory = sessionmaker(bind=engine,autoflush=True)
        databaseSession = scoped_session(session_factory)
        resource.databaseSession = databaseSession
    def process_response(self, req, resp, resource, req_succeeded):
        if hasattr(resource, 'mainDatabase'):
            if not req_succeeded:
                resource.databaseSession.rollback()
            self.databaseSession.remove()

Ответы [ 2 ]

0 голосов
/ 10 апреля 2019

В сочетании с SQLAlchemy я использую SQLService в качестве уровня интерфейса для менеджера сеансов SQLAlchemy и уровня ORM, который хорошо централизует основные функциональные возможности SQLAlchemy.

Вот мое определение компонента промежуточного программного обеспечения:

class DatabaseSessionComponent(object):
    """ Initiates a new Session for incoming request and closes it in the end. """

    def __init__(self, sqlalchemy_database_uri):
        self.sqlalchemy_database_uri = sqlalchemy_database_uri

    def process_resource(self, req, resp, resource, params):
        resource.db = sqlservice.SQLClient(
            {
                "SQL_DATABASE_URI": self.sqlalchemy_database_uri,
                "SQL_ISOLATION_LEVEL": "SERIALIZABLE",
                "SQL_ECHO": False,
                "SQL_ECHO_POOL": False,
                "SQL_CONVERT_UNICODE": True,
                "SQL_POOL_RECYCLE": 3600,
                "SQL_AUTOCOMMIT": False,
                "SQL_AUTOFLUSH": True,
                "SQL_EXPIRE_ON_COMMIT": True,
            },
            model_class=BaseModel,
        )

    def process_response(self, req, resp, resource):
        if hasattr(resource, "db"):
            resource.db.disconnect()

С его экземпляром в экземпляре API здесь:

api = falcon.API(
    middleware=[
        DatabaseSessionComponent(os.environ["SQLALCHEMY_DATABASE_URI"]),
    ]
)
0 голосов
/ 13 января 2019

Ваш подход, вероятно, неверен, поскольку он противоречит предполагаемой схеме использования экземпляров двигателя, описанной в утилизация двигателя . Время жизни экземпляра движка должно быть таким же, как и у экземпляра промежуточного программного обеспечения.

Под Engine понимается пул соединений, что означает, что в обычных условиях имеются открытые соединения с базой данных, пока объект Engine все еще находится в памяти. Когда Engine собирает мусор, его пул соединений больше не упоминается этим движком, и, при условии, что ни одно из его соединений все еще не извлечено, пул и его соединения также будут собираться мусором, что приводит к закрытию фактического подключения к базе данных. Но в противном случае Engine будет удерживать открытые соединения с базой данных, предполагая, что он обычно использует реализацию пула QueuePool по умолчанию.

Двигатель, как правило, предназначен для использования в качестве постоянного приспособления, установленного заранее и обслуживаемого в течение всего срока службы приложения. Он не предназначен для создания и утилизации для каждого соединения; вместо этого это реестр, который поддерживает как пул соединений, так и информацию о конфигурации используемой базы данных и DBAPI, а также некоторую степень внутреннего кэширования ресурсов для каждой базы данных.

...