From a66c555126bd6e6590909bc0c7f3c92ec4c0e339 Mon Sep 17 00:00:00 2001 From: Matthew McGinn Date: Wed, 27 Sep 2017 07:57:23 -0400 Subject: [PATCH] adding retry logic for all requests.exceptions adding an exponential backoff with jitter on POST calls reducing the number of retries in some of the tests to comply with the backoff feature. pass through all requests.exceptions after the permitted number of retries. --- influxdb/client.py | 30 ++++++++++++++++++++---------- influxdb/tests/client_test.py | 10 +++++----- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index 2b6dc689..5e1f0c81 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -7,6 +7,8 @@ from __future__ import unicode_literals from sys import version_info +import time +import random import json import socket @@ -237,6 +239,7 @@ def request(self, url, method='GET', params=None, data=None, _try = 0 while retry: try: + _error = False response = self._session.request( method=method, url=url, @@ -249,20 +252,27 @@ def request(self, url, method='GET', params=None, data=None, timeout=self._timeout ) break - except requests.exceptions.ConnectionError: + except (requests.exceptions.ConnectionError, + requests.exceptions.HTTPError, + requests.exceptions.Timeout) as _e: + _error = _e _try += 1 if self._retries != 0: retry = _try < self._retries - - else: - raise requests.exceptions.ConnectionError - - if 500 <= response.status_code < 600: - raise InfluxDBServerError(response.content) - elif response.status_code == expected_response_code: - return response + if method == "POST": + time.sleep((2 ** _try) * random.random() / 100.0) + if _error: + raise(_error) else: - raise InfluxDBClientError(response.content, response.status_code) + # if there's not an error, there must have been a successful + # response + if 500 <= response.status_code < 600: + raise InfluxDBServerError(response.content) + elif response.status_code == expected_response_code: + return response + else: + raise InfluxDBClientError(response.content, + response.status_code) def write(self, data, params=None, expected_response_code=204, protocol='json'): diff --git a/influxdb/tests/client_test.py b/influxdb/tests/client_test.py index 5c4f26dd..3413c0bf 100644 --- a/influxdb/tests/client_test.py +++ b/influxdb/tests/client_test.py @@ -686,7 +686,7 @@ def connection_error(self, *args, **kwargs): @mock.patch('requests.Session.request') def test_request_retry_raises(self, mock_request): - """Test that three connection errors will not be handled.""" + """Test that three requests errors will not be handled.""" class CustomMock(object): """Create custom mock object for test.""" @@ -698,7 +698,7 @@ def connection_error(self, *args, **kwargs): self.i += 1 if self.i < 4: - raise requests.exceptions.ConnectionError + raise requests.exceptions.HTTPError else: r = requests.Response() r.status_code = 200 @@ -708,7 +708,7 @@ def connection_error(self, *args, **kwargs): cli = InfluxDBClient(database='db') - with self.assertRaises(requests.exceptions.ConnectionError): + with self.assertRaises(requests.exceptions.HTTPError): cli.write_points(self.dummy_points) @mock.patch('requests.Session.request') @@ -732,7 +732,7 @@ def connection_error(self, *args, **kwargs): r.status_code = 204 return r - retries = random.randint(1, 100) + retries = random.randint(1, 5) mock_request.side_effect = CustomMock(retries).connection_error cli = InfluxDBClient(database='db', retries=retries) @@ -759,7 +759,7 @@ def connection_error(self, *args, **kwargs): r.status_code = 200 return r - retries = random.randint(1, 100) + retries = random.randint(1, 5) mock_request.side_effect = CustomMock(retries).connection_error cli = InfluxDBClient(database='db', retries=retries)