Skip to content

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:
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:

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.

@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:

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.