42 lines
1 KiB
Python
42 lines
1 KiB
Python
"""Shared clients that live for the lifetime of the FastAPI process.
|
|
|
|
We keep one AtomicClient, one EmbeddingClient, and one TagResolver in module
|
|
state. FastAPI dependencies pull them out so handlers stay clean.
|
|
|
|
Initialized from app.py's lifespan context manager at startup; closed on
|
|
shutdown.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from shared.atomic_api import AtomicClient
|
|
from shared.embedding_client import EmbeddingClient
|
|
from shared.llm_client import LlmClient
|
|
from shared.taxonomy import TagResolver
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class AppState:
|
|
atomic: AtomicClient
|
|
embed: EmbeddingClient
|
|
llm: LlmClient
|
|
resolver: TagResolver
|
|
|
|
|
|
# Module-level singleton, populated by the lifespan handler.
|
|
_state: AppState | None = None
|
|
|
|
|
|
def set_state(state: AppState) -> None:
|
|
global _state
|
|
_state = state
|
|
|
|
|
|
def get_state() -> AppState:
|
|
if _state is None:
|
|
raise RuntimeError(
|
|
"brain_api state not initialized — FastAPI lifespan must run first"
|
|
)
|
|
return _state
|