"""Database configuration and session management.""" from contextlib import asynccontextmanager from typing import AsyncGenerator from sqlalchemy.ext.asyncio import ( AsyncSession, async_sessionmaker, create_async_engine, ) from sqlalchemy.orm import DeclarativeBase from app.core.config import settings # Create async engine engine = create_async_engine( settings.DATABASE_URL, echo=settings.DEBUG, future=True, pool_pre_ping=True, pool_size=10, max_overflow=20, ) # Create async session factory async_session_maker = async_sessionmaker( engine, class_=AsyncSession, expire_on_commit=False, autocommit=False, autoflush=False, ) class Base(DeclarativeBase): """Base class for all SQLAlchemy models.""" pass async def get_db() -> AsyncGenerator[AsyncSession, None]: """ Dependency function to get database session. Yields: AsyncSession: Database session. Example: @app.get("/users/") async def get_users(db: AsyncSession = Depends(get_db)): result = await db.execute(select(User)) return result.scalars().all() """ async with async_session_maker() as session: try: yield session await session.commit() except Exception: await session.rollback() raise finally: await session.close() @asynccontextmanager async def get_db_context() -> AsyncGenerator[AsyncSession, None]: """ Context manager for database session. Yields: AsyncSession: Database session. Example: async with get_db_context() as db: await db.execute(insert(User).values(**user_data)) """ async with async_session_maker() as session: try: yield session await session.commit() except Exception: await session.rollback() raise finally: await session.close() async def init_db() -> None: """Initialize database tables.""" async with engine.begin() as conn: # Import all models here to ensure they're registered with Base from app.models import ( # noqa: F401 album, artist, playlist, playlist_track, track, user, ) # Create all tables await conn.run_sync(Base.metadata.create_all) async def close_db() -> None: """Close database connections.""" await engine.dispose()