Spaces:
Sleeping
Sleeping
| import time | |
| import logging | |
| import psycopg2 | |
| from contextlib import contextmanager | |
| from src.config import settings | |
| logger = logging.getLogger("cashy.db") | |
| NEON_RETRY_DELAY = 3 # seconds to wait for Neon cold start | |
| def _connect(): | |
| """Create a psycopg2 connection, retrying once on cold-start failures.""" | |
| conn_kwargs = dict( | |
| host=settings.db_host, | |
| port=settings.db_port, | |
| dbname=settings.resolved_db_name, | |
| user=settings.db_user, | |
| password=settings.db_password, | |
| ) | |
| if settings.db_sslmode: | |
| conn_kwargs["sslmode"] = settings.db_sslmode | |
| try: | |
| return psycopg2.connect(**conn_kwargs) | |
| except psycopg2.OperationalError: | |
| logger.info("DB connection failed -- retrying in %ds (Neon cold start?)", NEON_RETRY_DELAY) | |
| time.sleep(NEON_RETRY_DELAY) | |
| return psycopg2.connect(**conn_kwargs) | |
| def get_connection(): | |
| """Context manager for database connections. | |
| Usage: | |
| with get_connection() as conn: | |
| with conn.cursor() as cur: | |
| cur.execute("SELECT ...") | |
| rows = cur.fetchall() | |
| """ | |
| logger.debug("Opening DB connection") | |
| conn = _connect() | |
| try: | |
| yield conn | |
| except Exception: | |
| logger.warning("DB error -- rolling back") | |
| conn.rollback() | |
| raise | |
| else: | |
| conn.commit() | |
| finally: | |
| conn.close() | |
| logger.debug("DB connection closed") | |