| """ |
| Database connection and session management |
| """ |
| from contextlib import asynccontextmanager |
| from typing import AsyncGenerator |
|
|
| from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine |
|
|
| from ..config import settings |
| from .logging import get_logger |
|
|
| logger = get_logger(__name__) |
|
|
| |
| engine = create_async_engine( |
| settings.database_url, |
| echo=settings.app_env == "local", |
| pool_pre_ping=True, |
| pool_size=10, |
| max_overflow=20, |
| ) |
|
|
| |
| async_session_factory = async_sessionmaker( |
| engine, |
| class_=AsyncSession, |
| expire_on_commit=False, |
| ) |
|
|
|
|
| @asynccontextmanager |
| async def get_db_session() -> AsyncGenerator[AsyncSession, None]: |
| """Get database session with automatic cleanup""" |
| async with async_session_factory() as session: |
| try: |
| yield session |
| await session.commit() |
| except Exception: |
| await session.rollback() |
| raise |
| finally: |
| await session.close() |
|
|
|
|
| async def init_database() -> None: |
| """Initialize database tables""" |
| from ..models import Base |
| |
| logger.info("Initializing database...") |
| async with engine.begin() as conn: |
| await conn.run_sync(Base.metadata.create_all) |
| logger.info("Database initialized successfully") |
|
|
|
|
| async def close_database() -> None: |
| """Close database connections""" |
| logger.info("Closing database connections...") |
| await engine.dispose() |
| logger.info("Database connections closed") |
|
|