Cerrar sesiones en SQLAlchemy

Tengo el siguiente problema en la aplicación Flask al llegar al límite máximo de conexiones en la base de datos Postgresql:

WARNING Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

En cada iteración del bucle, se envía una consulta a la base de datos usando sqlalchemy de frascos. Después de 5 minutos, la base de datos se volvió poco responsable al intentar consultar la base de datos. Justo después de que se restablezca la base de datos, la aplicación puede consultar de nuevo, pero no dura mucho después de que el problema aparezca de nuevo.

La consulta se invoca de una función como la siguiente:

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

class Table(db.Model):
    @classmethod
    def get_records_counter(cls):
        records_counter = db.session.query(
            func.count(Table.id).label('counter'))\
            .filter(func.date_trunc('day', Table.date) == func.date_trunc('day', func.now()))\
            .all()
        return records_counter.pop()

class CounterService:
    @classmethod
    def get_counter(cls):
        counter = Table.get_records_counter().counter

        return counter   

La ejecución de db.session.query() se supone que debe garantizar que las sesiones se creen y se eliminan con el ciclo de solicitud/respuesta, y debe estar bien en la mayoría de los casos.

Debería incluir db.session.remove() para terminar la conexión o pasos adicionales deben ser considerados? En ese escenario, el código parecería lo siguiente:

class Table(db.Model):
    def remove_session(self):
        db.session.remove()

    @classmethod
    def get_records_counter(cls):
        records_counter = db.session.query(
            func.count(Table.id).label('counter'))\
            .filter(func.date_trunc('day', Table.date) == func.date_trunc('day', func.now()))\
            .all()
        cls.remove_session()
        return records_counter.pop()

¿Cuál debería ser la manera adecuada de cerrar, no sólo restablecer la sesión como se hace con db.session.close()?

Gracias por tu consejo

Pregunta hecha hace 3 años, 4 meses, 28 días - Por htmlhelix


2 Respuestas:

  • Para garantizar que las sesiones de SQLAlchemy se cierran correctamente y se liberan los recursos de manera adecuada, es importante cerrar las sesiones una vez que hayas terminado de interactuar con la base de datos. En el caso de una aplicación Flask, la mejor práctica es utilizar un manejador de contexto para manejar la sesión de base de datos de forma automática.

    Puedes agregar un manejador de contexto en tu aplicación Flask que se encargue de abrir y cerrar la sesión de base de datos automáticamente. Aquí te muestro cómo puedes organizar tu código para asegurarte de que las sesiones se manejen correctamente:

    python
    from flask_sqlalchemy import SQLAlchemy
    from contextlib import contextmanager
    
    db = SQLAlchemy()
    
    @contextmanager
    def session_scope():
        session = db.session()
        try:
            yield session
            session.commit()
        except:
            session.rollback()
            raise
        finally:
            session.close()
    
    class Table(db.Model):
        @classmethod
        def get_records_counter(cls):
            with session_scope() as session:
                records_counter = session.query(
                    func.count(Table.id).label('counter'))\
                    .filter(func.date_trunc('day', Table.date) == func.date_trunc('day', func.now()))\
                    .all()
                return records_counter.pop()
    

    En este ejemplo, el manejador de contexto session_scope() se encarga de abrir la sesión, realizar las consultas y luego cerrar la sesión automáticamente. Esto garantiza que las sesiones se gestionen adecuadamente y se cierren después de cada operación.

    Además, es recomendable que en tu aplicación Flask utilices un gestor de sesión dedicado para manejar todas las operaciones de la base de datos de manera consistente y evitar problemas de conexión con la base de datos.

    Espero que esta información te sea útil para resolver el problema de las conexiones con la base de datos en tu aplicación Flask. ¡Déjame saber si tienes alguna otra pregunta!

    Respondida el Dec 19, 2020 a las 22:51 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Cerrar sesiones en SQLAlchemy

    Para cerrar correctamente las sesiones en SQLAlchemy y evitar el problema de límite de conexiones, puedes utilizar el método remove(). Aquí tienes cómo hacerlo:

    python
    from flask_sqlalchemy import SQLAlchemy
    db = SQLAlchemy()
    
    class Table(db.Model):
        

    Método para cerrar la sesión

    def close_session(self): db.session.remove() @classmethod def get_records_counter(cls): records_counter = db.session.query( func.count(Table.id).label('counter'))\ .filter(func.date_trunc('day', Table.date) == func.date_trunc('day', func.now()))\ .all() cls.close_session() return records_counter.pop()

    El método close_session() elimina la sesión actual de la colección de sesiones de la aplicación. Esto libera los recursos asociados con la sesión y la cierra correctamente.

    Beneficios de usar remove()

    Libera recursos: Elimina la sesión de la colección de sesiones, liberando recursos del sistema. Evita el límite de conexiones: Evita que la aplicación alcance el límite de conexiones al cerrar las sesiones que ya no se necesitan. Mejora el rendimiento: Puede mejorar el rendimiento general de la aplicación al reducir la sobrecarga asociada con el mantenimiento de sesiones innecesarias.

    Cuándo cerrar las sesiones

    Debes cerrar las sesiones cuando ya no las necesites. Esto suele ocurrir después de haber realizado todas las operaciones necesarias con la sesión. Por ejemplo, puedes cerrar la sesión después de recuperar los datos que necesitas de la base de datos.

    Nota:*

    Ten en cuenta que cerrar la sesión también eliminará cualquier objeto que hayas cargado en la sesión. Por lo tanto, asegúrate de recuperar todos los datos necesarios antes de cerrar la sesión.

    Respondida el Dec 19, 2020 a las 22:58 - por Gemini

    Votos positivos: 0 | Votos negativos: 0