FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
51 lines
1.3 KiB
Python
51 lines
1.3 KiB
Python
"""Async SQLAlchemy engine/session setup.
|
|
|
|
Works against Postgres (`postgresql+psycopg://...`) or SQLite
|
|
(`sqlite+aiosqlite://...`) depending on `DATABASE_URL` - the same models and
|
|
repositories run against either, which is what makes the no-Docker local dev
|
|
path possible.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import AsyncGenerator
|
|
from functools import lru_cache
|
|
|
|
from sqlalchemy.ext.asyncio import (
|
|
AsyncEngine,
|
|
AsyncSession,
|
|
async_sessionmaker,
|
|
create_async_engine,
|
|
)
|
|
|
|
from app.core.config import get_settings
|
|
|
|
|
|
@lru_cache
|
|
def get_engine() -> AsyncEngine:
|
|
settings = get_settings()
|
|
connect_args = {}
|
|
if settings.database_url.startswith("sqlite"):
|
|
connect_args = {"check_same_thread": False}
|
|
return create_async_engine(
|
|
settings.database_url,
|
|
echo=False,
|
|
pool_pre_ping=True,
|
|
connect_args=connect_args,
|
|
)
|
|
|
|
|
|
@lru_cache
|
|
def get_sessionmaker() -> async_sessionmaker[AsyncSession]:
|
|
return async_sessionmaker(bind=get_engine(), expire_on_commit=False)
|
|
|
|
|
|
async def get_db() -> AsyncGenerator[AsyncSession, None]:
|
|
session_factory = get_sessionmaker()
|
|
async with session_factory() as session:
|
|
try:
|
|
yield session
|
|
except Exception:
|
|
await session.rollback()
|
|
raise
|