playreel/backend/utils/database.py

59 lines
1.6 KiB
Python

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