Convert the ebook-search web app to async end to end and add concurrency to the protected-phrase extraction and judging pipeline so large books no longer block the event loop or the UI. ORM / infra: - Add get_async_postgres_engine and factor shared URL/connect_args building into build_postgres_url (reused by the sync and async engine builders) - Add async FastAPI session helpers (get_async_db, AsyncDbSession) with expire_on_commit=False to avoid implicit IO under asyncio App: - Use AsyncEngine/AsyncSession throughout routes, search, ingest, embeddings, answer, rerank and LLM calls; convert handlers to async - Share a single httpx.AsyncClient in app state for LLM requests; size the connection pool for concurrent phrase-judging workers - Add judge_tasks: run per-book judging as tracked background tasks so a book already being judged isn't double-queued Protected phrases: - Add a process pool (pool.py) and worker-count config (extraction/judge book/phrase workers) to parallelize candidate generation and judging - Split admin actions into all/missing variants for generation and judging Config: - Add protected_phrase_extraction_workers, phrase_judge_book_workers, phrase_judge_phrase_workers
32 lines
910 B
Python
32 lines
910 B
Python
"""FastAPI dependencies for the EPUB search app."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Annotated
|
|
|
|
import httpx
|
|
from fastapi import Depends, Request
|
|
from sqlalchemy.ext.asyncio import AsyncEngine
|
|
|
|
from python.ebook_search.config import EbookSearchConfig
|
|
|
|
|
|
def get_config(request: Request) -> EbookSearchConfig:
|
|
"""Get the loaded search config from app state."""
|
|
return request.app.state.config
|
|
|
|
|
|
def get_engine(request: Request) -> AsyncEngine:
|
|
"""Get the database engine from app state."""
|
|
return request.app.state.engine
|
|
|
|
|
|
def get_http_client(request: Request) -> httpx.AsyncClient:
|
|
"""Get the shared LLM HTTP client from app state."""
|
|
return request.app.state.http_client
|
|
|
|
|
|
AppConfig = Annotated[EbookSearchConfig, Depends(get_config)]
|
|
AppEngine = Annotated[AsyncEngine, Depends(get_engine)]
|
|
AppHttpClient = Annotated[httpx.AsyncClient, Depends(get_http_client)]
|