| import os | |
| import socket | |
| from sqlalchemy import create_engine | |
| from sqlalchemy.orm import sessionmaker | |
| from src.backend.database.candidates.models import Base | |
| from src.backend.configs import get_database_settings | |
| def get_engine(): | |
| """ | |
| Builds a SQLAlchemy engine using validated environment variables. | |
| Works seamlessly in both local and Docker environments. | |
| Priority: | |
| 1. Environment variables (e.g., POSTGRES_HOST from Docker) | |
| 2. .env file defaults via Pydantic config | |
| """ | |
| settings = get_database_settings() | |
| # Allow POSTGRES_HOST override; strip whitespace/quotes to avoid DNS issues | |
| raw_host = os.getenv("POSTGRES_HOST", settings.host) | |
| postgres_host = raw_host.strip().strip("\"'") | |
| # If 'db' (compose) is not resolvable (single-container run), fall back to host.docker.internal | |
| try: | |
| socket.gethostbyname(postgres_host) | |
| except Exception: | |
| fallback = os.getenv("POSTGRES_HOST_FALLBACK", "host.docker.internal").strip().strip("\"'") | |
| print(f"[db-client] Host '{postgres_host}' not resolvable; falling back to '{fallback}'") | |
| postgres_host = fallback | |
| database_url = ( | |
| f"postgresql+psycopg2://{settings.user}:{settings.password}" | |
| f"@{postgres_host}:{settings.port}/{settings.db}" | |
| ) | |
| print(f"[db-client] Connecting to database at host={postgres_host} port={settings.port} db={settings.db} user={settings.user}", flush=True) | |
| return create_engine(database_url, echo=False, future=True) | |
| # --- SQLAlchemy session setup --- | |
| engine = get_engine() | |
| SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False) | |