68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
"""Async database engine and session helpers."""
|
|
|
|
from collections.abc import AsyncGenerator
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker, create_async_engine
|
|
|
|
from app.config.settings import get_settings
|
|
from app.infra.db.base import Base
|
|
|
|
_engine: AsyncEngine | None = None
|
|
_session_factory: async_sessionmaker[AsyncSession] | None = None
|
|
|
|
|
|
def get_async_engine() -> AsyncEngine:
|
|
"""Return the lazily created async SQLAlchemy engine."""
|
|
|
|
global _engine
|
|
if _engine is None:
|
|
_engine = create_async_engine(
|
|
get_settings().database_url,
|
|
future=True,
|
|
echo=False,
|
|
)
|
|
return _engine
|
|
|
|
|
|
def get_session_factory() -> async_sessionmaker[AsyncSession]:
|
|
"""Return the lazily created async session factory."""
|
|
|
|
global _session_factory
|
|
if _session_factory is None:
|
|
_session_factory = async_sessionmaker(get_async_engine(), expire_on_commit=False)
|
|
return _session_factory
|
|
|
|
|
|
async def get_db_session() -> AsyncGenerator[AsyncSession, None]:
|
|
"""Yield a database session for FastAPI dependencies."""
|
|
|
|
async with get_session_factory()() as session:
|
|
yield session
|
|
|
|
|
|
async def init_database() -> None:
|
|
"""Create database tables when running the MVP without migrations."""
|
|
|
|
from app.infra.db.models.asset import AssetORM
|
|
from app.infra.db.models.library_resource import LibraryResourceORM
|
|
from app.infra.db.models.library_resource_file import LibraryResourceFileORM
|
|
from app.infra.db.models.order import OrderORM
|
|
from app.infra.db.models.review_task import ReviewTaskORM
|
|
from app.infra.db.models.workflow_run import WorkflowRunORM
|
|
from app.infra.db.models.workflow_step import WorkflowStepORM
|
|
|
|
del AssetORM, LibraryResourceORM, LibraryResourceFileORM, OrderORM, ReviewTaskORM, WorkflowRunORM, WorkflowStepORM
|
|
|
|
async with get_async_engine().begin() as connection:
|
|
await connection.run_sync(Base.metadata.create_all)
|
|
|
|
|
|
async def dispose_database() -> None:
|
|
"""Dispose the active engine and clear cached session objects."""
|
|
|
|
global _engine, _session_factory
|
|
if _engine is not None:
|
|
await _engine.dispose()
|
|
_engine = None
|
|
_session_factory = None
|