@@ -54,19 +54,44 @@ async def handle_async_request(self, request: httpx.Request) -> httpx.Response:
5454
5555
5656class ConnectionRetryTransport (RetryTransport ):
57- """Retry only failures establishing the connection, matching the
58- connect-only ``retries`` of the httpx transport this replaced: pyqwest
59- raises the builtin ``ConnectionError`` only before the request was
60- written, so these retries can never replay a request the API may have
61- received. The retry middleware's default policy would otherwise also
62- retry I/O errors and 429/5xx responses for idempotent methods."""
57+ """Retry only failures establishing the connection — shared by the REST
58+ API and envd RPC stacks: pyqwest raises the builtin ``ConnectionError``
59+ only before the request was written, so these retries can never replay a
60+ request the server may have received (a delivered REST call or unary RPC
61+ like ``SendInput``). This matches the connect-only ``retries`` of the
62+ httpx transports this replaced; the retry middleware's default policy
63+ would otherwise also retry I/O errors and 429/5xx responses for
64+ idempotent methods."""
6365
6466 def should_retry_response (
6567 self , request : Request , response : Union [Response , Exception ]
6668 ) -> bool :
6769 return isinstance (response , ConnectionError )
6870
6971
72+ def retrying_http_transport (
73+ proxy : Optional [ProxyConfig ],
74+ ) -> ConnectionRetryTransport :
75+ """A fresh pyqwest transport (= its own connection pool) with the SDK's
76+ shared tuning — system CA certs (without which TLS through an
77+ intercepting proxy fails), the httpx-equivalent pool limits, and
78+ connect-only retries. The REST API and envd RPC stacks each cache their
79+ own instances (pool unification is a follow-up).
80+ Requests are logged by pyqwest itself on the ``pyqwest.access`` and
81+ ``pyqwest`` loggers at ``DEBUG`` (off unless enabled) — the transport-level
82+ diagnostics httpcore used to provide. The SDK's own ``logger`` option is
83+ separate and sits above this, on the httpx client."""
84+ return ConnectionRetryTransport (
85+ HTTPTransport (
86+ tls_include_system_certs = True ,
87+ proxy = proxy .to_pyqwest () if proxy is not None else None ,
88+ pool_idle_timeout = pool_idle_timeout ,
89+ pool_max_idle_per_host = pool_max_idle_per_host ,
90+ ),
91+ max_retries = connection_retries ,
92+ )
93+
94+
7095_transport_lock = threading .Lock ()
7196# One transport (= one connection pool) per proxy; None is the direct pool.
7297# pyqwest's I/O runs on its own Rust runtime, so unlike the httpx envd
@@ -78,27 +103,12 @@ def should_retry_response(
78103def get_transport (config : ConnectionConfig ) -> "AsyncApiPyqwestTransport" :
79104 """The shared pyqwest-backed httpx transport for REST API calls. For TLS
80105 connections ALPN negotiates the HTTP version (HTTP/2 against the E2B
81- API), like the http2-enabled httpx transport this replaced.
82-
83- Requests are logged by pyqwest itself on the ``pyqwest.access`` and
84- ``pyqwest`` loggers at ``DEBUG`` (off unless enabled) — the transport-level
85- diagnostics httpcore used to provide. The SDK's own ``logger`` option is
86- separate and sits above this, on the httpx client."""
106+ API), like the http2-enabled httpx transport this replaced."""
87107 proxy = proxy_to_config (config .proxy )
88108 with _transport_lock :
89109 transport = _transports .get (proxy )
90110 if transport is None :
91- transport = AsyncApiPyqwestTransport (
92- ConnectionRetryTransport (
93- HTTPTransport (
94- tls_include_system_certs = True ,
95- proxy = proxy .to_pyqwest () if proxy is not None else None ,
96- pool_idle_timeout = pool_idle_timeout ,
97- pool_max_idle_per_host = pool_max_idle_per_host ,
98- ),
99- max_retries = connection_retries ,
100- )
101- )
111+ transport = AsyncApiPyqwestTransport (retrying_http_transport (proxy ))
102112 _transports [proxy ] = transport
103113 return transport
104114
0 commit comments