Skip to content

Commit ad50454

Browse files
committed
Fix #553: don't retry 4XX errors in Jira client
1 parent 9d5c5dd commit ad50454

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

jbi/services/common.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
ServiceHealth = dict[str, bool]
2121

2222

23-
def instrument(prefix: str, exceptions: Sequence[Type[Exception]]):
23+
def instrument(prefix: str, exceptions: Sequence[Type[Exception]], **backoff_params):
2424
"""This decorator wraps a function such that it increments a counter every
2525
time it is called and times its execution. It retries the function if the
2626
specified exceptions are raised.
@@ -32,6 +32,7 @@ def decorator(func):
3232
backoff.expo,
3333
exceptions,
3434
max_tries=settings.max_retries + 1,
35+
**backoff_params,
3536
)
3637
def wrapper(*args, **kwargs):
3738
# Increment the call counter.

jbi/services/jira.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,23 @@
3030

3131
JIRA_DESCRIPTION_CHAR_LIMIT = 32767
3232

33+
34+
def fatal_code(e):
35+
# Do not retry 4XX errors, mark them as fatal.
36+
try:
37+
return 400 <= e.response.status_code < 500
38+
except AttributeError:
39+
# `ApiError` or `ConnectionError` won't have response attribute.
40+
return False
41+
42+
3343
instrumented_method = instrument(
3444
prefix="jira",
3545
exceptions=(
3646
atlassian_errors.ApiError,
3747
requests_exceptions.RequestException,
3848
),
49+
giveup=fatal_code,
3950
)
4051

4152

tests/unit/services/test_jira.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,22 @@ def test_jira_retries_failing_connections_in_health_check(
8787
assert len(mocked_responses.calls) == 4
8888

8989

90+
@pytest.mark.no_mocked_jira
91+
def test_jira_does_not_retry_4XX(mocked_responses, context_create_example):
92+
url = f"{get_settings().jira_base_url}rest/api/2/issue"
93+
mocked_responses.add(
94+
responses.POST,
95+
url,
96+
json={},
97+
status=400,
98+
)
99+
100+
with pytest.raises(requests.HTTPError):
101+
jira.create_jira_issue(context=context_create_example, description="")
102+
103+
assert len(mocked_responses.calls) == 1
104+
105+
90106
@pytest.mark.parametrize(
91107
"jira_components, project_components, expected_result",
92108
[

0 commit comments

Comments
 (0)