Skip to content

Commit 7de027a

Browse files
authored
Merge pull request #75 from cloudblue/LITE-28571-fix-too-many-open-files
LITE-28571 cache transports by endpoint address
2 parents 1285ce9 + 17ecf5b commit 7de027a

3 files changed

Lines changed: 50 additions & 21 deletions

File tree

connect/client/fluent.py

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import httpx
1212
import requests
13+
from requests.adapters import HTTPAdapter
1314

1415
from connect.client.constants import CONNECT_ENDPOINT_URL, CONNECT_SPECS_URL
1516
from connect.client.help_formatter import DefaultFormatter
@@ -24,7 +25,11 @@
2425
from connect.client.utils import get_headers
2526

2627

27-
class _ConnectClientBase(threading.local):
28+
_SYNC_TRANSPORTS = {}
29+
_ASYNC_TRANSPORTS = {}
30+
31+
32+
class _ConnectClientBase:
2833
def __init__(
2934
self,
3035
api_key,
@@ -53,25 +58,11 @@ def __init__(
5358
self.specs = None
5459
if self._use_specs:
5560
self.specs = OpenAPISpecs(self.specs_location)
56-
self._response = None
5761
self.logger = logger
5862
self._help_formatter = DefaultFormatter(self.specs)
5963
self.timeout = timeout
6064
self.resourceset_append = resourceset_append
6165

62-
@property
63-
def response(self) -> requests.Response:
64-
"""
65-
Returns the raw
66-
[`requests`](https://requests.readthedocs.io/en/latest/api/#requests.Response)
67-
response.
68-
"""
69-
return self._response
70-
71-
@response.setter
72-
def response(self, value: requests.Response):
73-
self._response = value
74-
7566
def __getattr__(self, name):
7667
if '_' in name:
7768
name = name.replace('_', '-')
@@ -173,7 +164,7 @@ def _get_api_error_details(self):
173164
pass
174165

175166

176-
class ConnectClient(_ConnectClientBase, threading.local, SyncClientMixin):
167+
class ConnectClient(_ConnectClientBase, SyncClientMixin):
177168
"""
178169
Create a new instance of the ConnectClient.
179170
@@ -203,7 +194,33 @@ class ConnectClient(_ConnectClientBase, threading.local, SyncClientMixin):
203194

204195
def __init__(self, *args, **kwargs):
205196
super().__init__(*args, **kwargs)
206-
self._session = requests.Session()
197+
self._thread_locals = threading.local()
198+
self._thread_locals.response = None
199+
self._thread_locals.session = requests.Session()
200+
self._thread_locals.session.mount(
201+
self.endpoint,
202+
_SYNC_TRANSPORTS.setdefault(
203+
self.endpoint,
204+
HTTPAdapter(),
205+
),
206+
)
207+
208+
@property
209+
def session(self):
210+
return self._thread_locals.session
211+
212+
@property
213+
def response(self) -> requests.Response:
214+
"""
215+
Returns the raw
216+
[`requests`](https://requests.readthedocs.io/en/latest/api/#requests.Response)
217+
response.
218+
"""
219+
return self._thread_locals.response
220+
221+
@response.setter
222+
def response(self, value: requests.Response):
223+
self._thread_locals.response = value
207224

208225
def _get_collection_class(self):
209226
return Collection
@@ -246,7 +263,19 @@ class AsyncConnectClient(_ConnectClientBase, AsyncClientMixin):
246263
def __init__(self, *args, **kwargs):
247264
super().__init__(*args, **kwargs)
248265
self._response = contextvars.ContextVar('response', default=None)
249-
self._session = httpx.AsyncClient(verify=_SSL_CONTEXT)
266+
self._session = contextvars.ContextVar(
267+
'session',
268+
default=httpx.AsyncClient(
269+
transport=_ASYNC_TRANSPORTS.setdefault(
270+
self.endpoint,
271+
httpx.AsyncHTTPTransport(verify=_SSL_CONTEXT),
272+
),
273+
),
274+
)
275+
276+
@property
277+
def session(self):
278+
return self._session.get()
250279

251280
@property
252281
def response(self):

connect/client/mixins.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def _execute_http_call(self, method, url, kwargs): # noqa: CCR001
9999
if self.logger:
100100
self.logger.log_request(method, url, kwargs)
101101
try:
102-
self.response = self._session.request(method, url, **kwargs)
102+
self.response = self.session.request(method, url, **kwargs)
103103
if self.logger:
104104
self.logger.log_response(self.response)
105105
except RequestException:
@@ -209,7 +209,7 @@ async def _execute_http_call(self, method, url, kwargs):
209209
self.logger.log_request(method, url, kwargs)
210210

211211
try:
212-
self.response = await self._session.request(method, url, **kwargs)
212+
self.response = await self.session.request(method, url, **kwargs)
213213

214214
if self.logger:
215215
self.logger.log_response(self.response)

tests/client/test_fluent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,4 +549,4 @@ def test_sync_client_manage_response():
549549
c = ConnectClient('API_KEY')
550550
assert c.response is None
551551
c.response = 'Some response'
552-
assert c._response == 'Some response'
552+
assert c._thread_locals.response == 'Some response'

0 commit comments

Comments
 (0)