Limits are not honoured when using httpx-retries without Custom Transport #3567
-
|
httpx.Client or httpx.AsyncClient Client Code part of import httpx
from httpx_retries import Retry, RetryTransport
retries = Retry(
total=3,
backoff_factor=0.2,
status_forcelist=[500, 502, 503, 504],
allowed_methods=["HEAD", "GET", "POST", "PUT", "DELETE", "OPTIONS"],
)
transport = RetryTransport(retry=retries)
session = httpx.Client(
transport=transport,
http2=True,
limits=httpx.Limits(max_connections=100, max_keepalive_connections=100, keepalive_expiry=60),
headers={
"User-Agent": f"Python/{__version__}",
"Content-Type": "application/json",
},
)
return sessionIn SDK Interface: class SDKClient:
def _init__():
self.http_sync_client = SyncHttpSessionManager()
def authorize(request):
return self.http_sync_client.post(....)Usage for i in range(5):
start_time = time.monotonic()
response = client.authorize(request=request)
logger.info(f"Time taken for response={(time.monotonic() - start_time) * 1000:.2f} ms. Sleeping for 6 (default+1) second to test keep-alive. ")
time.sleep(6) We intentionally put a sleep above and can see in logs that connection are getting closed after 5 seconds 2025-05-09 17:43:39,184 - level=INFO logger=[client] Time taken for response=1747.09 ms. Sleeping for 6 (default+1) second to test keep-alive.
2025-05-09 17:43:46,998 - level=INFO logger=[client] Time taken for response=1809.17 ms. Sleeping for 6 (default+1) second to test keep-alive.
2025-05-09 17:43:54,755 - level=INFO logger=[client] Time taken for response=1754.75 ms. Sleeping for 6 (default+1) second to test keep-alive.
2025-05-09 17:44:02,629 - level=INFO logger=[client] Time taken for response=1869.00 ms. Sleeping for 6 (default+1) second to test keep-alive.
2025-05-09 17:44:10,402 - level=INFO logger=[client] Time taken for response=1769.34 ms. Sleeping for 6 (default+1) second to test keep-alive. when sleep is 4 seconds, the first call took 1784.65, however other re-used the connection: 2025-05-09 17:50:33,642 - level=INFO logger=[client] Time taken for response=1784.65 ms. Sleeping for 4 second to test keep-alive.
2025-05-09 17:50:37,946 - level=INFO logger=[client] Time taken for response=300.42 ms. Sleeping for 4 second to test keep-alive.
2025-05-09 17:50:42,265 - level=INFO logger=[client] Time taken for response=314.88 ms. Sleeping for 4 second to test keep-alive.
2025-05-09 17:50:46,571 - level=INFO logger=[client] Time taken for response=300.44 ms. Sleeping for 4 second to test keep-alive.
2025-05-09 17:50:50,884 - level=INFO logger=[client] Time taken for response=310.29 ms. Sleeping for 4 second to test keep-alive. As a work-around, created a custom transport = httpx.HTTPTransport(
limits=httpx.Limits(max_connections=100, max_keepalive_connections=100, keepalive_expiry=60)
)
transport = RetryTransport(retry=retries, transport=transport)Again, added wait for 6 seconds again, but this time keep-alive is honored. Should Limit passed to client be preferred or this is expected behavior? Opened an issue on httpx-retries as well will-ockmore/httpx-retries#17 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
As noted on the linked issue on https://github.com/will-ockmore/httpx-retries , this is currently expected behaviour for any custom transport passed to Perhaps we could add a docs issue to clarify this as it's probably a bit confusing. Unless the behaviour itself is unintuitive, and would be better off fixed; but it's not clear to me that it is intuitive to override transport behaviour (and limits is definitely transport behaviour) from the client. Both approaches can be confusing in different scenarios! |
Beta Was this translation helpful? Give feedback.
As noted on the linked issue on https://github.com/will-ockmore/httpx-retries , this is currently expected behaviour for any custom transport passed to
httpx.Client.Perhaps we could add a docs issue to clarify this as it's probably a bit confusing. Unless the behaviour itself is unintuitive, and would be better off fixed; but it's not clear to me that it is intuitive to override transport behaviour (and limits is definitely transport behaviour) from the client. Both approaches can be confusing in different scenarios!