| """Database connection pooling — Redis + Postgres with auto-reconnect.""" |
|
|
| import logging |
| import os |
|
|
| logger = logging.getLogger(__name__) |
|
|
| REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0") |
| PG_URL = os.getenv("DATABASE_URL", "postgresql://postgres:postgres@localhost:5432/postgres") |
|
|
| _redis_pool = None |
| _pg_pool = None |
|
|
|
|
| def get_redis(): |
| """Get or create Redis connection pool. Auto-reconnects.""" |
| global _redis_pool |
| if _redis_pool is None: |
| import redis |
|
|
| try: |
| _redis_pool = redis.ConnectionPool.from_url( |
| REDIS_URL, max_connections=20, retry_on_timeout=True, health_check_interval=30 |
| ) |
| logger.info("Redis pool created (max 20)") |
| except Exception as e: |
| logger.error(f"Redis pool failed: {e}") |
| return None |
| import redis |
|
|
| return redis.Redis(connection_pool=_redis_pool) |
|
|
|
|
| def get_postgres(): |
| """Get or create Postgres connection pool.""" |
| global _pg_pool |
| if _pg_pool is None: |
| try: |
| from psycopg2 import pool |
|
|
| _pg_pool = pool.ThreadedConnectionPool(5, 20, PG_URL) |
| logger.info("Postgres pool created (5-20)") |
| except Exception as e: |
| logger.error(f"Postgres pool failed: {e}") |
| return None |
| return _pg_pool.getconn() |
|
|
|
|
| def return_postgres(conn): |
| """Return connection to pool.""" |
| if _pg_pool and conn: |
| _pg_pool.putconn(conn) |
|
|
|
|
| def pool_stats() -> dict: |
| """Get connection pool statistics.""" |
| return { |
| "redis": {"pool_size": 20, "active": "unknown"} if _redis_pool else {"error": "no pool"}, |
| "postgres": {"min": 5, "max": 20} if _pg_pool else {"error": "no pool"}, |
| } |
|
|