"""MySQL 비동기 세션. FastAPI 의존성으로 쓴다: async def handler(session: AsyncSession = Depends(get_session)): ... """ from collections.abc import AsyncGenerator from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import DeclarativeBase from sqlalchemy.pool import AsyncQueuePool from settings import settings POOL_SIZE = 10 MAX_OVERFLOW = 10 POOL_TIMEOUT = 30 POOL_RECYCLE = 3600 # 연결을 1시간마다 새로 맺는다 class Base(DeclarativeBase): pass engine = create_async_engine( settings.mysql_url, pool_size=POOL_SIZE, max_overflow=MAX_OVERFLOW, poolclass=AsyncQueuePool, pool_timeout=POOL_TIMEOUT, pool_recycle=POOL_RECYCLE, pool_pre_ping=True, # 끊긴 연결을 쓰기 전에 걸러낸다 pool_reset_on_return="rollback", echo=False, connect_args={ "connect_timeout": 10, "read_timeout": 30, "write_timeout": 30, "charset": "utf8mb4", "sql_mode": "STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE", "init_command": "SET SESSION time_zone = '+00:00'", }, ) session_factory = async_sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False, autoflush=False) async def get_session() -> AsyncGenerator[AsyncSession, None]: async with session_factory() as session: try: yield session except Exception: await session.rollback() raise async def close_engine() -> None: await engine.dispose()