Skip to content

refactor: replace per-call httpx clients with module-level singletons#67

Open
bolinocroustibat wants to merge 1 commit intomainfrom
refactor/httpx-singleton-clients
Open

refactor: replace per-call httpx clients with module-level singletons#67
bolinocroustibat wants to merge 1 commit intomainfrom
refactor/httpx-singleton-clients

Conversation

@bolinocroustibat
Copy link
Collaborator

@bolinocroustibat bolinocroustibat commented Mar 5, 2026

Memray profiling of a live LLM session revealed that every outbound HTTP call was creating a fresh httpx.AsyncClient, performing a full TLS handshake, and immediately closing it. With ~40 outbound calls per session (API lookups + Matomo pings), this accumulated 295 MB of SSL context allocations, all transient but entirely unnecessary.

This PR replaces the per-call pattern with a module-level singleton client in each helper (datagouv_api_client, tabular_api_client, crawler_api_client, metrics_api_client, matomo). Connections are now pooled and reused across requests, eliminating repeated TLS handshakes.

  • The optional session parameter is preserved on all public functions as a dependency-injection hook for tests
  • pytest-asyncio is configured with a session-scoped event loop (asyncio_default_test_loop_scope = session) so the shared clients work correctly across the test suite without "event loop is closed" teardown errors

Each helper module previously created a new httpx.AsyncClient on every
function call and closed it immediately after, causing a full TLS handshake
on every outbound request. A memray profiling session showed this pattern
accounted for 295 MB of cumulative SSL context allocations across a single
short LLM session (~40 outbound calls).

Each helper now holds one shared AsyncClient created at import time. The
optional `session` parameter is kept on all public functions as a test
override hook. pytest-asyncio is configured with a session-scoped event
loop so module-level clients survive across tests without triggering
"event loop is closed" errors on teardown.

Made-with: Cursor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant