Skip to content

perf(notifications,ecm): pool outbound httpx clients + lifecycle close (v26.06.70)#97

Merged
ancongui merged 3 commits into
mainfrom
perf/pool-http-clients
Jun 7, 2026
Merged

perf(notifications,ecm): pool outbound httpx clients + lifecycle close (v26.06.70)#97
ancongui merged 3 commits into
mainfrom
perf/pool-http-clients

Conversation

@ancongui
Copy link
Copy Markdown
Contributor

@ancongui ancongui commented Jun 7, 2026

Audit efficiency fix: 7 outbound provider adapters (notifications SendGrid/Resend/Twilio/Firebase, ECM DocuSign/Adobe Sign/Logalty) built a new httpx.AsyncClient per call — no connection reuse. Now each keeps one lazily-created pooled client, reused across calls, and closes it on shutdown via added start()/stop() lifecycle (the ApplicationContext calls them).

A shared PooledHttpClient async-context wrapper yields the shared client without closing it on __aexit__, so the existing async with await self._client() call sites (1 per notifier, 3 per ECM adapter) stay unchanged — minimal diff, same behavior, pooled connections. Tests (3). Gates: mypy --strict (637), ruff+format, full suite 3941.

Andrés Contreras Guillén added 3 commits June 7, 2026 21:09
…e + bump v26.06.70

The audit found 7 provider adapters built a NEW httpx.AsyncClient per call (no pooling):
notifications/providers/{sendgrid,resend,twilio,firebase} + ecm/adapters/{docusign,adobe_sign,logalty}.
Now each keeps one lazily-created pooled client and closes it on stop() (added start/stop lifecycle
so the ApplicationContext closes it). New pyfly.client.pooled.PooledHttpClient async-CM wrapper yields
the shared client without closing on __aexit__, so the existing 'async with await self._client()' call
sites (1 in each notifier, 3 each in the ECM adapters) are unchanged.

Tests: tests/client/test_pooled_http_client.py (3 — wrapper no-close, email + ecm pool-and-close).
Gates: mypy --strict (637), ruff + format, full suite 3941 passed.
…ip on startup failure

CI 3.12 had a Docker daemon but couldn't pull images (registry timeout), so @requires_docker passed
but the postgres/redis integration fixtures ERRORED on container start instead of skipping. Moved
the redis_url/pg_url fixtures into tests/integration/conftest.py with a try/except that pytest.skips
on ANY container-startup failure (image pull, daemon issues) — so the suite degrades to skipped, not
errored, wherever Docker isn't fully functional. Removed the now-duplicate local fixtures + unused imports.
@ancongui ancongui merged commit cc862c6 into main Jun 7, 2026
5 checks passed
@ancongui ancongui deleted the perf/pool-http-clients branch June 7, 2026 19:19
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