Skip to content

Commit 071bf9c

Browse files
authored
Merge pull request #927 from simvue-io/925-python-api-no-longer-retries-requests-which-may-have-temporarily-failed-eg-502
Seeing if creating a pull request triggers a GitHub action
2 parents 4992ebf + 682552e commit 071bf9c

File tree

2 files changed

+66
-23
lines changed

2 files changed

+66
-23
lines changed

simvue/api/request.py

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import requests
1717
from tenacity import (
1818
retry,
19-
retry_if_exception,
19+
retry_if_exception_type,
2020
stop_after_attempt,
2121
wait_exponential,
2222
)
@@ -29,14 +29,7 @@
2929
RETRY_MAX = 10
3030
RETRY_STOP = 5
3131
MAX_ENTRIES_PER_PAGE: int = 100
32-
RETRY_STATUS_CODES = (
33-
http.HTTPStatus.BAD_REQUEST,
34-
http.HTTPStatus.SERVICE_UNAVAILABLE,
35-
http.HTTPStatus.GATEWAY_TIMEOUT,
36-
http.HTTPStatus.REQUEST_TIMEOUT,
37-
http.HTTPStatus.TOO_EARLY,
38-
)
39-
RETRY_EXCEPTION_TYPES = (RuntimeError, requests.exceptions.ConnectionError)
32+
RETRY_STATUSES = {502, 503, 504}
4033

4134

4235
def set_json_header(headers: dict[str, str]) -> dict[str, str]:
@@ -49,18 +42,20 @@ def set_json_header(headers: dict[str, str]) -> dict[str, str]:
4942
return headers
5043

5144

52-
def is_retryable_exception(exception: Exception) -> bool:
53-
"""Returns if the given exception should lead to a retry being called"""
54-
if isinstance(exception, requests.HTTPError):
55-
return exception.response.status_code in RETRY_STATUS_CODES
56-
57-
return isinstance(exception, RETRY_EXCEPTION_TYPES)
45+
class RetryableHTTPError(Exception):
46+
pass
5847

5948

6049
@retry(
6150
wait=wait_exponential(multiplier=RETRY_MULTIPLIER, min=RETRY_MIN, max=RETRY_MAX),
6251
stop=stop_after_attempt(RETRY_STOP),
63-
retry=retry_if_exception(is_retryable_exception),
52+
retry=retry_if_exception_type(
53+
(
54+
RetryableHTTPError,
55+
requests.exceptions.Timeout,
56+
requests.exceptions.ConnectionError,
57+
)
58+
),
6459
reraise=True,
6560
)
6661
def post(
@@ -114,12 +109,23 @@ def post(
114109
f"Validation error for '{url}' [{response.status_code}]:\n{_parsed_response}"
115110
)
116111

112+
if response.status_code in RETRY_STATUSES:
113+
raise RetryableHTTPError(
114+
f"Received status code {response.status_code} from server"
115+
)
116+
117117
return response
118118

119119

120120
@retry(
121121
wait=wait_exponential(multiplier=RETRY_MULTIPLIER, min=RETRY_MIN, max=RETRY_MAX),
122-
retry=retry_if_exception(is_retryable_exception),
122+
retry=retry_if_exception_type(
123+
(
124+
RetryableHTTPError,
125+
requests.exceptions.Timeout,
126+
requests.exceptions.ConnectionError,
127+
)
128+
),
123129
stop=stop_after_attempt(RETRY_STOP),
124130
reraise=True,
125131
)
@@ -161,14 +167,27 @@ def put(
161167

162168
logging.debug(f"PUT: {url}\n\tdata={data_sent}\n\tjson={json}")
163169

164-
return requests.put(
170+
response = requests.put(
165171
url, headers=headers, data=data_sent, timeout=timeout, json=json
166172
)
167173

174+
if response.status_code in RETRY_STATUSES:
175+
raise RetryableHTTPError(
176+
f"Received status code {response.status_code} from server"
177+
)
178+
179+
return response
180+
168181

169182
@retry(
170183
wait=wait_exponential(multiplier=RETRY_MULTIPLIER, min=RETRY_MIN, max=RETRY_MAX),
171-
retry=retry_if_exception(is_retryable_exception),
184+
retry=retry_if_exception_type(
185+
(
186+
RetryableHTTPError,
187+
requests.exceptions.Timeout,
188+
requests.exceptions.ConnectionError,
189+
)
190+
),
172191
stop=stop_after_attempt(RETRY_STOP),
173192
reraise=True,
174193
)
@@ -198,12 +217,27 @@ def get(
198217
response from executing GET
199218
"""
200219
logging.debug(f"GET: {url}\n\tparams={params}")
201-
return requests.get(url, headers=headers, timeout=timeout, params=params, json=json)
220+
response = requests.get(
221+
url, headers=headers, timeout=timeout, params=params, json=json
222+
)
223+
224+
if response.status_code in RETRY_STATUSES:
225+
raise RetryableHTTPError(
226+
f"Received status code {response.status_code} from server"
227+
)
228+
229+
return response
202230

203231

204232
@retry(
205233
wait=wait_exponential(multiplier=RETRY_MULTIPLIER, min=RETRY_MIN, max=RETRY_MAX),
206-
retry=retry_if_exception(is_retryable_exception),
234+
retry=retry_if_exception_type(
235+
(
236+
RetryableHTTPError,
237+
requests.exceptions.Timeout,
238+
requests.exceptions.ConnectionError,
239+
)
240+
),
207241
stop=stop_after_attempt(RETRY_STOP),
208242
reraise=True,
209243
)
@@ -232,7 +266,14 @@ def delete(
232266
response from executing DELETE
233267
"""
234268
logging.debug(f"DELETE: {url}\n\tparams={params}")
235-
return requests.delete(url, headers=headers, timeout=timeout, params=params)
269+
response = requests.delete(url, headers=headers, timeout=timeout, params=params)
270+
271+
if response.status_code in RETRY_STATUSES:
272+
raise RetryableHTTPError(
273+
f"Received status code {response.status_code} from server"
274+
)
275+
276+
return response
236277

237278

238279
def get_json_from_response(

simvue/run.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,9 @@ def _get_internal_metrics(
379379
# Set join on fail to false as if an error is thrown
380380
# join would be called on this thread and a thread cannot
381381
# join itself!
382-
if self.status == "running":
382+
if self.status == "running" and (
383+
self._shutdown_event and not self._shutdown_event.is_set()
384+
):
383385
self._add_metrics_to_dispatch(
384386
_current_system_measure.to_dict(),
385387
join_on_fail=False,

0 commit comments

Comments
 (0)