diff --git a/qdrant_client/http/api_client.py b/qdrant_client/http/api_client.py index 4c907c3cf..fda3596c8 100644 --- a/qdrant_client/http/api_client.py +++ b/qdrant_client/http/api_client.py @@ -183,6 +183,8 @@ async def request( # noqa F811 # in order to do a correct join, url join requires base_url to end with /, and url to not start with /, # since url is treated as an absolute path and might truncate prefix in base_url url = urljoin(host, url.format(**path_params)) + if "params" in kwargs and "timeout" in kwargs["params"]: + kwargs["timeout"] = int(kwargs["params"]["timeout"]) request = self._async_client.build_request(method, url, **kwargs) return await self.send(request, type_) diff --git a/tests/test_qdrant_client.py b/tests/test_qdrant_client.py index db7651203..41f313e9e 100644 --- a/tests/test_qdrant_client.py +++ b/tests/test_qdrant_client.py @@ -8,6 +8,7 @@ from pprint import pprint from tempfile import mkdtemp from time import sleep +from unittest.mock import patch import numpy as np import pytest @@ -1757,6 +1758,35 @@ def test_timeout_propagation(): ) +def test_async_rest_timeout_propagation(): + # Regression for #1325: async client dropped the per-call `timeout=` + # from kwargs before build_request, leaving callers bound by httpx's + # default 5s timeout. Sync ApiClient.request already promotes it. + from qdrant_client.http.api_client import AsyncApiClient + from unittest.mock import AsyncMock + + captured: dict = {} + + def _capture(method, url, **kwargs): + captured["kwargs"] = kwargs + return type("DummyRequest", (), {"headers": {}})() + + async_client = AsyncApiClient(host="http://localhost:6333") + with patch.object(async_client._async_client, "build_request", _capture), \ + patch.object(async_client, "send", new=AsyncMock()): + asyncio.run( + async_client.request( + type_=None, + method="GET", + url="/collections/{c}", + path_params={"c": "x"}, + params={"timeout": "50"}, + ) + ) + + assert captured["kwargs"].get("timeout") == 50 + + def test_grpc_options(): client_version = importlib.metadata.version("qdrant-client") user_agent = f"python-client/{client_version}"