Skip to content

Commit 91ed4d6

Browse files
authored
Merge pull request #36 from cloudblue/retry-on-timeout
retry on timeouts
2 parents 1e5d6bd + 384dca2 commit 91ed4d6

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

connect/client/mixins.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from httpx import HTTPError
1313

14-
from requests.exceptions import RequestException
14+
from requests.exceptions import RequestException, Timeout
1515

1616
from connect.client.exceptions import ClientError
1717

@@ -70,16 +70,21 @@ def execute(self, method, path, **kwargs):
7070
status_code = self.response.status_code if self.response is not None else None
7171
raise ClientError(status_code=status_code, **api_error) from re
7272

73-
def _execute_http_call(self, method, url, kwargs):
73+
def _execute_http_call(self, method, url, kwargs): # noqa: CCR001
7474
retry_count = 0
7575
while True:
7676
if self.logger:
7777
self.logger.log_request(method, url, kwargs)
78-
79-
self.response = requests.request(method, url, **kwargs)
80-
81-
if self.logger:
82-
self.logger.log_response(self.response)
78+
try:
79+
self.response = requests.request(method, url, **kwargs)
80+
if self.logger:
81+
self.logger.log_response(self.response)
82+
except Timeout:
83+
if retry_count < self.max_retries:
84+
retry_count += 1
85+
time.sleep(1)
86+
continue
87+
raise
8388

8489
if ( # pragma: no branch
8590
self.response.status_code >= 500

tests/client/test_fluent.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import responses
66

7-
from requests import RequestException
7+
from requests import RequestException, Timeout
88

99
from connect.client.constants import CONNECT_ENDPOINT_URL, CONNECT_SPECS_URL
1010
from connect.client.exceptions import ClientError
@@ -205,18 +205,27 @@ def test_execute_non_json_response(mocked_responses):
205205
assert result == b'This is a non json response.'
206206

207207

208-
def test_execute_retries(mocked_responses):
208+
@pytest.mark.parametrize(
209+
'mock_config',
210+
(
211+
{'status': 500},
212+
{'status': 501},
213+
{'status': 502},
214+
{'body': Timeout()},
215+
),
216+
)
217+
def test_execute_retries(mocked_responses, mock_config):
209218
expected = [{'id': i} for i in range(10)]
210219
mocked_responses.add(
211220
responses.GET,
212221
'https://localhost/resources',
213-
status=502,
222+
**mock_config,
214223
)
215224

216225
mocked_responses.add(
217226
responses.GET,
218227
'https://localhost/resources',
219-
status=502,
228+
**mock_config,
220229
)
221230

222231
mocked_responses.add(
@@ -245,26 +254,31 @@ def test_execute_retries(mocked_responses):
245254

246255

247256
@pytest.mark.parametrize(
248-
'code',
249-
[500, 501, 502],
257+
'mock_config',
258+
(
259+
{'status': 500},
260+
{'status': 501},
261+
{'status': 502},
262+
{'body': Timeout()},
263+
),
250264
)
251-
def test_execute_max_retries_exceeded(code, mocked_responses):
265+
def test_execute_max_retries_exceeded(mocked_responses, mock_config):
252266
mocked_responses.add(
253267
responses.GET,
254268
'https://localhost/resources',
255-
status=code,
269+
**mock_config,
256270
)
257271

258272
mocked_responses.add(
259273
responses.GET,
260274
'https://localhost/resources',
261-
status=code,
275+
**mock_config,
262276
)
263277

264278
mocked_responses.add(
265279
responses.GET,
266280
'https://localhost/resources',
267-
status=code,
281+
**mock_config,
268282
)
269283

270284
c = ConnectClient(
@@ -327,7 +341,7 @@ def test_execute_with_kwargs(mocked_responses):
327341
assert 'X-Custom-Header' in headers and headers['X-Custom-Header'] == 'value'
328342

329343

330-
def test_execute_with_overwritten_timeout(mocked_responses, mocker):
344+
def test_execute_with_overwritten_timeout(mocker):
331345
http_call = mocker.patch(
332346
'connect.client.mixins.SyncClientMixin._execute_http_call',
333347
side_effect=RequestException(),
@@ -354,7 +368,7 @@ def test_execute_with_overwritten_timeout(mocked_responses, mocker):
354368
)
355369

356370

357-
def test_execute_with_default_timeout(mocked_responses, mocker):
371+
def test_execute_with_default_timeout(mocker):
358372
http_call = mocker.patch(
359373
'connect.client.mixins.SyncClientMixin._execute_http_call',
360374
side_effect=RequestException(),

0 commit comments

Comments
 (0)