From db08e39b6a3fa65cd0c72dd280363785c78a7f1d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:59:18 +0000 Subject: [PATCH 1/4] Initial plan From 6b7a4f15135855fd42a32fd1668002386abdb873 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:04:16 +0000 Subject: [PATCH 2/4] Add django-db-connection-pool for PostgreSQL connection pooling - Add django-db-connection-pool==1.2.6 to production requirements - Change production DB ENGINE to dj_db_conn_pool.backends.postgresql - Add PRE_PING to POOL_OPTIONS for connection health verification - Reduce MAX_OVERFLOW default from 20 to 5 to prevent connection exhaustion - Update production .env with aligned pool configuration Celery signals for closing DB connections were already in place. Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com> --- .envs/.production/.django | 10 +++------- config/settings/production.py | 8 +++----- requirements/production.txt | 1 + 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/.envs/.production/.django b/.envs/.production/.django index f391c161b..d5e1ddf28 100644 --- a/.envs/.production/.django +++ b/.envs/.production/.django @@ -52,17 +52,13 @@ FETCH_DATA_TIMEOUT=10 # Exemplo: 10 segundos DB_CONNECT_TIMEOUT=10 -# --- Opções de Pool de Conexões --- -# (Aplicável se você estiver usando uma biblioteca de pool de conexões integrada ao Django, -# como django-db-connection-pool, que reconheça POOL_OPTIONS.) +# --- Opções de Pool de Conexões (django-db-connection-pool) --- -# Tamanho mínimo do pool de conexões -# Exemplo: 10 conexões +# Tamanho do pool de conexões por worker DB_POOL_SIZE=10 # Número máximo de conexões extras que o pool pode criar em caso de pico -# Exemplo: 20 conexões de "overflow" -DB_MAX_OVERFLOW=20 +DB_MAX_OVERFLOW=5 # Tempo máximo (em segundos) que uma conexão pode viver antes de ser reciclada # Ajuda a evitar conexões "stale" ou "bad". Exemplo: 300 segundos (5 minutos) diff --git a/config/settings/production.py b/config/settings/production.py index 75fe9dc13..4353793b9 100755 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -16,17 +16,15 @@ DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405 DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=0) or env.int("DJANGO_CONN_MAX_AGE", default=60) # noqa F405 DATABASES["default"]["CONN_HEALTH_CHECKS"] = env.bool('DJANGO_CONN_HEALTH_CHECKS', True) -DATABASES["default"]["ENGINE"] = 'django_prometheus.db.backends.postgresql' -# Melhoria: Usando variáveis de ambiente para OPTIONS e POOL_OPTIONS com defaults +DATABASES["default"]["ENGINE"] = 'dj_db_conn_pool.backends.postgresql' DATABASES["default"]["OPTIONS"] = { "connect_timeout": env.int("DB_CONNECT_TIMEOUT", default=10), - # Adicione outras opções de conexão aqui se necessário } DATABASES["default"]["POOL_OPTIONS"] = { 'POOL_SIZE': env.int("DB_POOL_SIZE", default=10), - 'MAX_OVERFLOW': env.int("DB_MAX_OVERFLOW", default=20), + 'MAX_OVERFLOW': env.int("DB_MAX_OVERFLOW", default=5), 'RECYCLE': env.int("DB_RECYCLE", default=300), - # Adicione outras opções do pool aqui se necessário + 'PRE_PING': True, } # CACHES # ------------------------------------------------------------------------------ diff --git a/requirements/production.txt b/requirements/production.txt index d1119b5ff..96c49b970 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -20,6 +20,7 @@ gevent==24.2.1 # http://www.gevent.org/ # ============================================================================== psycopg2-binary==2.9.9 # https://github.com/psycopg/psycopg2 +django-db-connection-pool==1.2.6 # https://github.com/altairbow/django-db-connection-pool # ============================================================================== # EMAIL From 2913754f370b0e7b56d96f6d746ec1006674c533 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:06:44 +0000 Subject: [PATCH 3/4] Add custom DB backend combining connection pooling with Prometheus metrics Create core.db.backends.postgresql backend that inherits from both PGDatabaseWrapperMixin (connection pooling) and PrometheusDatabaseWrapper (metrics), preserving Prometheus database monitoring while using SQLAlchemy QueuePool for connection management. Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com> --- config/settings/production.py | 2 +- core/db/__init__.py | 0 core/db/backends/__init__.py | 0 core/db/backends/postgresql/__init__.py | 0 core/db/backends/postgresql/base.py | 17 +++++++++++++++++ 5 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 core/db/__init__.py create mode 100644 core/db/backends/__init__.py create mode 100644 core/db/backends/postgresql/__init__.py create mode 100644 core/db/backends/postgresql/base.py diff --git a/config/settings/production.py b/config/settings/production.py index 4353793b9..e6147616f 100755 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -16,7 +16,7 @@ DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405 DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=0) or env.int("DJANGO_CONN_MAX_AGE", default=60) # noqa F405 DATABASES["default"]["CONN_HEALTH_CHECKS"] = env.bool('DJANGO_CONN_HEALTH_CHECKS', True) -DATABASES["default"]["ENGINE"] = 'dj_db_conn_pool.backends.postgresql' +DATABASES["default"]["ENGINE"] = 'core.db.backends.postgresql' DATABASES["default"]["OPTIONS"] = { "connect_timeout": env.int("DB_CONNECT_TIMEOUT", default=10), } diff --git a/core/db/__init__.py b/core/db/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/core/db/backends/__init__.py b/core/db/backends/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/core/db/backends/postgresql/__init__.py b/core/db/backends/postgresql/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/core/db/backends/postgresql/base.py b/core/db/backends/postgresql/base.py new file mode 100644 index 000000000..d8b558291 --- /dev/null +++ b/core/db/backends/postgresql/base.py @@ -0,0 +1,17 @@ +""" +Custom PostgreSQL database backend that combines: +- Connection pooling from django-db-connection-pool (SQLAlchemy QueuePool) +- Prometheus metrics from django-prometheus + +This backend inherits from both mixins so that connections are managed +by a pool while still being tracked by Prometheus. +""" + +from dj_db_conn_pool.backends.postgresql.mixins import PGDatabaseWrapperMixin +from django_prometheus.db.backends.postgresql.base import ( + DatabaseWrapper as PrometheusDatabaseWrapper, +) + + +class DatabaseWrapper(PGDatabaseWrapperMixin, PrometheusDatabaseWrapper): + pass From 70cc4b3ca6dbbfa0fc696bf4feaf2c73e33b7ad2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:07:41 +0000 Subject: [PATCH 4/4] Add documentation for custom DB backend MRO and PRE_PING option Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com> --- config/settings/production.py | 2 +- core/db/backends/postgresql/base.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/config/settings/production.py b/config/settings/production.py index e6147616f..99adaea41 100755 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -24,7 +24,7 @@ 'POOL_SIZE': env.int("DB_POOL_SIZE", default=10), 'MAX_OVERFLOW': env.int("DB_MAX_OVERFLOW", default=5), 'RECYCLE': env.int("DB_RECYCLE", default=300), - 'PRE_PING': True, + 'PRE_PING': True, # Validates connections before use to avoid stale/broken connections } # CACHES # ------------------------------------------------------------------------------ diff --git a/core/db/backends/postgresql/base.py b/core/db/backends/postgresql/base.py index d8b558291..a562c9912 100644 --- a/core/db/backends/postgresql/base.py +++ b/core/db/backends/postgresql/base.py @@ -14,4 +14,12 @@ class DatabaseWrapper(PGDatabaseWrapperMixin, PrometheusDatabaseWrapper): + """ + PostgreSQL backend with connection pooling and Prometheus monitoring. + + MRO: PGDatabaseWrapperMixin is first so its get_new_connection() manages + the SQLAlchemy QueuePool. When the pool needs a new connection, it calls + through to PrometheusDatabaseWrapper which adds metrics tracking. + """ + pass