fix: apply provided timeout value to ClientTimeout.total (#16395)

This commit is contained in:
yellowsubmarine372 2025-11-11 12:37:42 +09:00 • committed by GitHub
parent 5f12e4be1e
commit b6dbd4fa28
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 44 additions and 0 deletions

View file

@ -18,6 +18,7 @@ from litellm.secret_managers.main import str_to_bool
AIOHTTP_EXC_MAP: Dict = {
# Order matters here, most specific exception first
# Timeout related exceptions
asyncio.TimeoutError: httpx.TimeoutException,
aiohttp.ServerTimeoutError: httpx.TimeoutException,
aiohttp.ConnectionTimeoutError: httpx.ConnectTimeout,
aiohttp.SocketTimeoutError: httpx.ReadTimeout,
@ -253,6 +254,7 @@ class LiteLLMAiohttpTransport(AiohttpTransport):
allow_redirects=False,
auto_decompress=False,
timeout=ClientTimeout(
total=timeout.get("read"),
sock_connect=timeout.get("connect"),
sock_read=timeout.get("read"),
connect=timeout.get("pool"),

View file

@ -255,6 +255,48 @@ def _make_mock_response(should_fail=False, fail_count={"count": 0}):
return MockResp()
@pytest.mark.asyncio
async def test_handle_async_request_total_timeout_triggers():
"""
Ensure that LiteLLMAiohttpTransport raises httpx.TimeoutException
when the total timeout duration elapses.
"""
import asyncio
from aiohttp import web
async def slow_handler(request):
await asyncio.sleep(0.3)
return web.Response(text="ok")
app = web.Application()
app.router.add_get("/", slow_handler)
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, "127.0.0.1", 0)
await site.start()
port = site._server.sockets[0].getsockname()[1]
def factory():
return aiohttp.ClientSession()
transport = LiteLLMAiohttpTransport(client=factory) # type: ignore
request = httpx.Request("GET", f"http://127.0.0.1:{port}/")
request.extensions["timeout"] = {
"connect": 0.1,
"read": 0.1,
"pool": 0.1,
"total": 0.1,
}
try:
with pytest.raises(httpx.TimeoutException):
await transport.handle_async_request(request)
finally:
await transport.aclose()
await runner.cleanup()
def _make_mock_session(closed=False):
"""Helper to create a mock aiohttp session"""