Skip to content

Commit bdc887e

Browse files
committed
Fixing the issue? Andrew's suggestion
1 parent f9458ce commit bdc887e

3 files changed

Lines changed: 17 additions & 4 deletions

File tree

src/cohere/base_client.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,8 @@ class AsyncBaseCohere:
15931593
The timeout to be used, in seconds, for requests. By default the timeout is 300 seconds, unless a custom httpx client is used, in which case this default is not enforced.
15941594
15951595
follow_redirects : typing.Optional[bool]
1596-
Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.
1596+
Whether the async client follows HTTP redirects. Defaults to True. Passed as allow_redirects
1597+
on each request; does NOT affect TCP connection reuse (connections are always pooled).
15971598
15981599
httpx_client : typing.Optional[httpx.AsyncClient]
15991600
The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
@@ -1625,19 +1626,25 @@ def __init__(
16251626
if token is None:
16261627
raise ApiError(body="The client must be instantiated be either passing in token or setting CO_API_KEY")
16271628

1628-
# Create aiohttp session if not provided
1629+
# Create aiohttp session if not provided.
1630+
# NOTE: force_close is intentionally NOT derived from follow_redirects.
1631+
# force_close controls TCP connection reuse (keep-alive pooling); setting it True
1632+
# causes every request to open and close a fresh TCP socket, exhausting the ephemeral
1633+
# port range (TIME_WAIT) when making thousands of concurrent calls.
1634+
# Redirect behaviour is handled per-request via allow_redirects instead.
16291635
if aiohttp_session is None:
16301636
timeout_config = aiohttp.ClientTimeout(total=_defaulted_timeout)
1631-
connector = aiohttp.TCPConnector(force_close=not follow_redirects) if follow_redirects is not None else aiohttp.TCPConnector()
1637+
connector = aiohttp.TCPConnector()
16321638
aiohttp_session = aiohttp.ClientSession(timeout=timeout_config, connector=connector)
1633-
1639+
16341640
self._client_wrapper = AsyncClientWrapper(
16351641
base_url=_get_base_url(base_url=base_url, environment=environment),
16361642
client_name=client_name,
16371643
token=token,
16381644
headers=headers,
16391645
aiohttp_session=aiohttp_session,
16401646
timeout=_defaulted_timeout,
1647+
follow_redirects=follow_redirects if follow_redirects is not None else True,
16411648
)
16421649
self._raw_client = AsyncRawBaseCohere(client_wrapper=self._client_wrapper)
16431650
self._v2: typing.Optional[AsyncV2Client] = None

src/cohere/core/client_wrapper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def __init__(
8787
timeout: typing.Optional[float] = None,
8888
async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None,
8989
aiohttp_session: aiohttp.ClientSession,
90+
follow_redirects: bool = True,
9091
):
9192
super().__init__(client_name=client_name, token=token, headers=headers, base_url=base_url, timeout=timeout)
9293
self._async_token = async_token
@@ -96,6 +97,7 @@ def __init__(
9697
base_timeout=self.get_timeout,
9798
base_url=self.get_base_url,
9899
async_base_headers=self.async_get_headers,
100+
follow_redirects=follow_redirects,
99101
)
100102

101103
async def async_get_headers(self) -> typing.Dict[str, str]:

src/cohere/core/http_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,12 +460,14 @@ def __init__(
460460
base_headers: typing.Callable[[], typing.Dict[str, str]],
461461
base_url: typing.Optional[typing.Callable[[], str]] = None,
462462
async_base_headers: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Dict[str, str]]]] = None,
463+
follow_redirects: bool = True,
463464
):
464465
self.base_url = base_url
465466
self.base_timeout = base_timeout
466467
self.base_headers = base_headers
467468
self.async_base_headers = async_base_headers
468469
self.aiohttp_session = aiohttp_session
470+
self.follow_redirects = follow_redirects
469471

470472
async def _get_headers(self) -> typing.Dict[str, str]:
471473
if self.async_base_headers is not None:
@@ -570,6 +572,7 @@ async def request(
570572
json=json_body,
571573
data=request_data,
572574
timeout=timeout,
575+
allow_redirects=self.follow_redirects,
573576
)
574577

575578
# Read response body and parse JSON for aiohttp compatibility
@@ -707,6 +710,7 @@ async def stream(
707710
json=json_body,
708711
data=request_data,
709712
timeout=timeout,
713+
allow_redirects=self.follow_redirects,
710714
) as response:
711715
# Add status_code property for backward compatibility
712716
if not hasattr(response, 'status_code'):

0 commit comments

Comments
 (0)