Skip to content

Commit 42e0093

Browse files
feat: add retry functionality to the splunk_rest_client (#392)
**Issue number:[ADDON-75327](https://splunk.atlassian.net/browse/ADDON-75327)** ## Summary Added functionality to retries requests. ### Changes Added "max_retries" to the "HTTPAdapter" and set it to 5. ### User experience No impact / potential reliability improvement ## Checklist If your change doesn't seem to apply, please leave them unchecked. * [x] I have performed a self-review of this change * [x] Changes have been tested * [ ] Changes are documented * [x] PR title follows [conventional commit semantics](https://www.conventionalcommits.org/en/v1.0.0/)
1 parent f02c2a3 commit 42e0093

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

solnlib/splunk_rest_client.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
import traceback
2727
from io import BytesIO
2828
from urllib.parse import quote
29+
from urllib3.util.retry import Retry
2930

3031
from splunklib import binding, client
3132

3233
from .net_utils import validate_scheme_host_port
3334
from .splunkenv import get_splunkd_access_info
3435

3536
__all__ = ["SplunkRestClient"]
37+
MAX_REQUEST_RETRIES = 5
3638

3739

3840
def _get_proxy_info(context):
@@ -98,10 +100,18 @@ def _request_handler(context):
98100
else:
99101
cert = None
100102

103+
retries = Retry(
104+
total=MAX_REQUEST_RETRIES,
105+
backoff_factor=0.3,
106+
status_forcelist=[500, 502, 503, 504],
107+
allowed_methods=["GET", "POST", "PUT", "DELETE"],
108+
raise_on_status=False,
109+
)
101110
if context.get("pool_connections", 0):
102111
logging.info("Use HTTP connection pooling")
103112
session = requests.Session()
104113
adapter = requests.adapters.HTTPAdapter(
114+
max_retries=retries,
105115
pool_connections=context.get("pool_connections", 10),
106116
pool_maxsize=context.get("pool_maxsize", 10),
107117
)

tests/unit/test_splunk_rest_client.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717
from unittest import mock
1818

1919
import pytest
20+
from solnlib.splunk_rest_client import MAX_REQUEST_RETRIES
2021

22+
from requests.exceptions import ConnectionError
2123
from solnlib import splunk_rest_client
24+
from solnlib.splunk_rest_client import SplunkRestClient
2225

2326

2427
@mock.patch.dict(os.environ, {"SPLUNK_HOME": "/opt/splunk"}, clear=True)
@@ -80,3 +83,29 @@ def test_init_with_invalid_port():
8083
host="localhost",
8184
port=99999,
8285
)
86+
87+
88+
@mock.patch.dict(os.environ, {"SPLUNK_HOME": "/opt/splunk"}, clear=True)
89+
@mock.patch("solnlib.splunk_rest_client.get_splunkd_access_info")
90+
@mock.patch("http.client.HTTPResponse")
91+
@mock.patch("urllib3.HTTPConnectionPool._make_request")
92+
def test_request_retry(http_conn_pool, http_resp, mock_get_splunkd_access_info):
93+
mock_get_splunkd_access_info.return_value = "https", "localhost", 8089
94+
session_key = "123"
95+
context = {"pool_connections": 5}
96+
rest_client = SplunkRestClient("msg_name_1", session_key, "_", **context)
97+
98+
mock_resp = http_resp()
99+
mock_resp.status = 200
100+
mock_resp.reason = "TEST OK"
101+
102+
side_effects = [ConnectionError(), ConnectionError(), ConnectionError(), mock_resp]
103+
http_conn_pool.side_effect = side_effects
104+
res = rest_client.get("test")
105+
assert http_conn_pool.call_count == len(side_effects)
106+
assert res.reason == mock_resp.reason
107+
108+
side_effects = [ConnectionError()] * (MAX_REQUEST_RETRIES + 1) + [mock_resp]
109+
http_conn_pool.side_effect = side_effects
110+
with pytest.raises(ConnectionError):
111+
rest_client.get("test")

0 commit comments

Comments
 (0)