Parece que no puedo hacer que mi aplicación Flask cierre o reutilice las conexiones DB. Estoy usando PostgreSQL 9.1.3 y¿Cómo hago que Flask SQLAlchemy reutilice las conexiones de db?
Flask==0.8
Flask-SQLAlchemy==0.16
psycopg2==2.4.5
Como mi banco de pruebas se ejecuta el número de conexiones abiertas sube hasta que llega a 20 (el ajuste max_connections
en postgresql.conf
), entonces veo:
OperationalError: (OperationalError) FATAL: sorry, too many clients already
None None
Reduje el código al punto en el que solo llama a create_all
y drop_all
(pero no emite ningún sql ya que no hay modelos).
I ver las conexiones que se comprueba y salir en los registros de:
DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost', closed: 0> checked out from pool
DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost', closed: 0> being returned to pool
WARNING:root:impl <-------- That's the test running
DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost', closed: 0> checked out from pool
DEBUG:sqlalchemy.pool.QueuePool:Connection <connection object at 0x101c1dff0; dsn: 'dbname=cx_test host=localhost', closed: 0> being returned to pool
Para cada ejecución de prueba de la dirección de la conexión (el "objeto de conexión en xyz" parte) es diferente. Sospecho que esto tiene algo que ver con el problema, pero no estoy seguro de cómo investigar más.
El código siguiente reproduce el problema de una nueva Venv:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from unittest import TestCase
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('sqlalchemy.pool').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.dialects').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.orm').setLevel(logging.DEBUG)
db = SQLAlchemy()
def create_app(config=None):
app = Flask(__name__)
app.config.from_object(config)
db.init_app(app)
return app
class AppTestCase(TestCase):
SQLALCHEMY_DATABASE_URI = "postgresql://localhost/cx_test"
TESTING = True
def create_app(self):
return create_app(self)
def setUp(self):
self.app = self.create_app()
self.client = self.app.test_client()
self._ctx = self.app.test_request_context()
self._ctx.push()
db.create_all()
def tearDown(self):
db.session.remove()
db.drop_all()
self._ctx.pop()
class TestModel(AppTestCase):
def impl(self):
logging.warn("impl")
pass
def test_01(self):
self.impl()
def test_02(self):
self.impl()
def test_03(self):
self.impl()
def test_04(self):
self.impl()
def test_05(self):
self.impl()
def test_06(self):
self.impl()
def test_07(self):
self.impl()
def test_08(self):
self.impl()
def test_09(self):
self.impl()
def test_10(self):
self.impl()
def test_11(self):
self.impl()
def test_12(self):
self.impl()
def test_13(self):
self.impl()
def test_14(self):
self.impl()
def test_15(self):
self.impl()
def test_16(self):
self.impl()
def test_17(self):
self.impl()
def test_18(self):
self.impl()
def test_19(self):
self.impl()
if __name__ == "__main__":
import unittest
unittest.main()
Esta es la primera vez que he utilizado fábricas de aplicaciones en el frasco, y he copiado el código en parte de la Flask-SQLAlchemy docs. Elseware esos documentos mencionan que usar un DB en el contexto incorrecto hará que las conexiones se filtren, ¿quizás estoy haciendo el init incorrectamente?
Gracias Van - eso resuelve el problema con el banco de pruebas, pero ¿no significa que estoy perdiendo menos conexiones? –
@TomDunham: supongo que tienes razón. no tienes 'postgres', así que no puedo ayudarte, lo siento ... – van