# Infra Adapters ## Summary All external systems are reached through adapters in `infra/`. Prefer an existing internal library over writing a new adapter. --- ## Database (MongoDB) - A single connection manager owns the client lifecycle. `setup_database(uri, db_name)` / `shutdown_database()`. - A repository **factory** selects the repository flavour: ```python repo_factory(collection, document, engine=None, populate_rules=None, cache=None) ``` - base repository — plain CRUD; - populating repository — resolves referenced documents (foreign keys); - cached repository — an LRU/TTL cache in front of reads. - Referenced documents are described declaratively: ```python PopulateRule(field="owner", collection="users", nested_rules=[], max_depth=2, projection=None) ``` - Transactions use a session context manager provided by the library. **Library:** the Mongo operations library (see registry). Do not write raw Motor calls in the domain. ## HTTP response cache A generic GET cache sits behind a decorator. ```python @cache_response(ttl=60) async def list_items(request): ... ``` - Keyed on path + query + user. - No-op when no store is wired. - `invalidate(*resources)` bumps a generation counter for write-triggered invalidation. ## Event / progress bus A port with an in-memory default adapter (`publish`, `get_events`). Swap for a durable broker in production (see Worker & Progress). ## External clients (ingestion) External fetchers (files, mail, HTTP) are adapters that wrap ingestion libraries. Construct them in the composition root and inject into orchestrators. **Libraries:** the ingestion library (formats) and the mail library (email). ## LLM clients When a pipeline calls a model provider, route through a pool adaptor that handles provider selection, retries, and client lifecycle: ```python pool = setup_async_pool(provider=settings.llm_provider) result = await pool.complete(model="...", messages=[...]) ``` Providers are selected by `LLM_PROVIDER` and configured by environment. ## Key-value store For report/snapshot storage, provide a pluggable store port with a Redis adapter and an in-memory fallback. ## Rule If a capability already exists as a library (DB, DI, ingestion, mail, auth, docs), **use it**. Writing a private copy of a library is a defect.