"""Async engine and session factory.""" from sqlalchemy import event from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.pool import StaticPool SessionMaker = async_sessionmaker[AsyncSession] def make_engine(url: str) -> AsyncEngine: if url.startswith("sqlite"): # In-memory SQLite lives per connection: share one connection so every session sees the same DB. kwargs = ( {"poolclass": StaticPool, "connect_args": {"check_same_thread": False}} if ":memory:" in url or url.endswith("://") else {} ) engine = create_async_engine(url, **kwargs) event.listen(engine.sync_engine, "connect", _sqlite_foreign_keys) return engine return create_async_engine(url, pool_pre_ping=True) def _sqlite_foreign_keys(dbapi_conn: object, _record: object) -> None: # SQLite ignores FOREIGN KEY / ON DELETE CASCADE unless asked per connection cursor = dbapi_conn.cursor() # type: ignore[attr-defined] cursor.execute("PRAGMA foreign_keys=ON") cursor.close() def make_sessionmaker(engine: AsyncEngine) -> SessionMaker: return async_sessionmaker(engine, expire_on_commit=False) __all__ = ["SessionMaker", "make_engine", "make_sessionmaker"]