yetuge ab168befae
fix(sandbox): build the readiness client off the event loop (#7934)
* fix(sandbox): build the readiness client off the event loop

`wait_for_sandbox_ready_async` exists so sandbox startup waits do not block the
runtime event loop, yet it constructed `httpx.AsyncClient` inline: the
constructor resolves the system trust store synchronously, so the loop stalled
for the whole construction before the first poll was sent (~320 ms in a local
probe on this host).

Move the construction into a worker thread and own it as a task, the way
backend/AGENTS.md now requires for HTTPX clients: a cancellation that lands
while the worker is still inside the constructor waits for it and closes the
client it builds, so the pool is not abandoned. Requests, polling cadence,
timeouts and cleanup stay on the event loop.

The blocking-I/O regression pins both halves. Against the previous code the
trust-store assertion fires on the loop thread; with a plain `asyncio.to_thread`
instead of the owned task, the cancellation test reports the leaked client.

* fix(sandbox): preserve readiness cancellation during cleanup

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-07 15:49:55 +08:00
..