Skip to content

Commit

Permalink
Add retries to get features (#218)
Browse files Browse the repository at this point in the history
* Add retries to get features

Create session and provide it with a custom HTTPAdapter, that has max_retries set.

Related issue: #217

* Fix Retry type

* Fix import, use urllib3.Retry instead of Sonarype suggestion
  • Loading branch information
janboll authored Sep 1, 2022
1 parent 615ca5b commit c47f071
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 12 deletions.
18 changes: 13 additions & 5 deletions UnleashClient/api/features.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from typing import Tuple
import requests
from UnleashClient.constants import REQUEST_TIMEOUT, FEATURES_URL
from requests.adapters import HTTPAdapter
from urllib3 import Retry

from UnleashClient.constants import REQUEST_TIMEOUT, FEATURES_URL, \
REQUEST_RETRIES
from UnleashClient.utils import LOGGER, log_resp_info


Expand Down Expand Up @@ -45,10 +49,14 @@ def get_feature_toggles(url: str,
if project:
base_params = {'project': project}

resp = requests.get(base_url,
headers={**custom_headers, **headers},
params=base_params,
timeout=REQUEST_TIMEOUT, **custom_options)
adapter = HTTPAdapter(max_retries=Retry(total=REQUEST_RETRIES, status_forcelist=[500, 502, 504]))
with requests.Session() as session:
session.mount("https://", adapter)
session.mount("http://", adapter)
resp = session.get(base_url,
headers={**custom_headers, **headers},
params=base_params,
timeout=REQUEST_TIMEOUT, **custom_options)

if resp.status_code not in [200, 304]:
log_resp_info(resp)
Expand Down
1 change: 1 addition & 0 deletions UnleashClient/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
SDK_NAME = "unleash-client-python"
SDK_VERSION = version("UnleashClient")
REQUEST_TIMEOUT = 30
REQUEST_RETRIES = 3
METRIC_LAST_SENT_TIME = "mlst"

# =Unleash=
Expand Down
33 changes: 26 additions & 7 deletions tests/unit_tests/api/test_feature.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import responses
from pytest import mark, param

from tests.utilities.mocks.mock_features import MOCK_FEATURE_RESPONSE, MOCK_FEATURE_RESPONSE_PROJECT
from tests.utilities.testing_constants import URL, APP_NAME, INSTANCE_ID, CUSTOM_HEADERS, CUSTOM_OPTIONS, PROJECT_URL, PROJECT_NAME, ETAG_VALUE
from UnleashClient.constants import FEATURES_URL
Expand All @@ -10,12 +11,12 @@


@responses.activate
@mark.parametrize("response,status,expected", (
param(MOCK_FEATURE_RESPONSE, 200, lambda result: result["version"] == 1, id="success"),
param(MOCK_FEATURE_RESPONSE, 202, lambda result: not result, id="failure"),
param({}, 500, lambda result: not result, id="failure"),
@mark.parametrize("response,status,calls,expected", (
param(MOCK_FEATURE_RESPONSE, 200, 1, lambda result: result["version"] == 1, id="success"),
param(MOCK_FEATURE_RESPONSE, 202, 1, lambda result: not result, id="failure"),
param({}, 500, 4, lambda result: not result, id="failure"),
))
def test_get_feature_toggle(response, status, expected):
def test_get_feature_toggle(response, status, calls, expected):
responses.add(responses.GET, FULL_FEATURE_URL, json=response, status=status, headers={'etag': ETAG_VALUE})

(result, etag) = get_feature_toggles(URL,
Expand All @@ -24,7 +25,7 @@ def test_get_feature_toggle(response, status, expected):
CUSTOM_HEADERS,
CUSTOM_OPTIONS)

assert len(responses.calls) == 1
assert len(responses.calls) == calls
assert expected(result)


Expand Down Expand Up @@ -55,7 +56,7 @@ def test_get_feature_toggle_failed_etag():
CUSTOM_OPTIONS,
PROJECT_NAME)

assert len(responses.calls) == 1
assert len(responses.calls) == 4
assert etag == ''


Expand All @@ -75,3 +76,21 @@ def test_get_feature_toggle_etag_present():
assert not result
assert responses.calls[0].request.headers['If-None-Match'] == ETAG_VALUE
assert etag == ETAG_VALUE


@responses.activate
def test_get_feature_toggle_retries():
responses.add(responses.GET, PROJECT_URL, json={}, status=500)
responses.add(responses.GET, PROJECT_URL, json=MOCK_FEATURE_RESPONSE_PROJECT, status=200, headers={'etag': ETAG_VALUE})

(result, etag) = get_feature_toggles(URL,
APP_NAME,
INSTANCE_ID,
CUSTOM_HEADERS,
CUSTOM_OPTIONS,
PROJECT_NAME,
ETAG_VALUE)

assert len(responses.calls) == 2
assert len(result["features"]) == 1
assert etag == ETAG_VALUE

0 comments on commit c47f071

Please sign in to comment.