|
|
""" |
|
|
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") |
|
|
|