Skip to content

Cache httpx AsyncClient per event loop to avoid cross-loop reuse crashes - #13410

Merged
cdrini merged 3 commits into
internetarchive:masterfrom
cdrini:async-client-per-event-loop
Aug 24, 2026
Merged

Cache httpx AsyncClient per event loop to avoid cross-loop reuse crashes#13410
cdrini merged 3 commits into
internetarchive:masterfrom
cdrini:async-client-per-event-loop

Conversation

@cdrini

@cdrini cdrini commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

We regularly get production RuntimeError: <asyncio.locks.Event object at 0x7f5816726ed0 [unset]> is bound to a different event loop errors while we do our migration to fastapi when the syncified version of an async method is called from fastapi. These should be removed/remedied, but it's not always possible to migrate everything in one fell swoop. This fix ensures that httpx.AsyncClient never crosses event loops so that these errors never happen, and we can migrate without having sporadic surprise errors on production.

A single shared httpx.AsyncClient used from both AsyncBridge's persistent background-thread event loop and a caller's own loop (e.g. FastAPI's) occasionally raised "RuntimeError: ... is bound to a different event loop", since httpx/httpcore/anyio lazily bind pooled-connection internals to whichever loop first contends for them. cache_per_event_loop() keeps one client per loop instead, preserving connection pooling/keep-alive/DNS caching within a loop while keeping different loops isolated.

Technical

Testing

Screenshot

Stakeholders

@github-project-automation github-project-automation Bot moved this to Waiting Review/Merge from Staff in Ray's Project Aug 24, 2026
@cdrini
cdrini force-pushed the async-client-per-event-loop branch 3 times, most recently from 7066670 to e793962 Compare August 24, 2026 19:18
@cdrini cdrini added the Patch Deployed This PR has been deployed to production independently, outside of the regular deploy cycle. label Aug 24, 2026

@RayBB RayBB left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great and works locally.

My main feedback is I don't think we should use subpreocess to grep. I suggested a fix below.

Comment thread scripts/check_no_bare_httpx_async_client.py
@cdrini
cdrini force-pushed the async-client-per-event-loop branch from e793962 to f07a8f1 Compare August 24, 2026 23:43
claude and others added 3 commits August 24, 2026 19:45
…sions

Co-Authored-By: Drini Cami <cdrini@gmail.com>
Co-Authored-By: RayBB <RayBB@users.noreply.github.com>
Co-Authored-By: Drini Cami <cdrini@gmail.com>
@cdrini
cdrini force-pushed the async-client-per-event-loop branch from f07a8f1 to 07590ff Compare August 24, 2026 23:46
@cdrini
cdrini merged commit b7aeca3 into internetarchive:master Aug 24, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from Waiting Review/Merge from Staff to Done in Ray's Project Aug 24, 2026
@cdrini
cdrini deleted the async-client-per-event-loop branch August 24, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Patch Deployed This PR has been deployed to production independently, outside of the regular deploy cycle.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants