Skip to content

Commit af90cb6

Browse files
committed
feat: exponential factor to 5, the maximal delay is 180_000 milliseconds, default retry interval is 5000
1 parent b00137b commit af90cb6

File tree

7 files changed

+37
-22
lines changed

7 files changed

+37
-22
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
### Features
44
1. [#136](https://github.com/influxdata/influxdb-client-python/pull/136): Allows users to skip of verifying SSL certificate
55
1. [#143](https://github.com/influxdata/influxdb-client-python/pull/143): Skip of verifying SSL certificate could be configured via config file or environment properties
6-
1. [#140](https://github.com/influxdata/influxdb-client-python/pull/140): Added exponential backoff strategy for batching writes, Allowed to configure default retry strategy
6+
1. [#140](https://github.com/influxdata/influxdb-client-python/pull/140): Added exponential backoff strategy for batching writes, Allowed to configure default retry strategy. Default value for `retry_interval` is 5_000 milliseconds.
77

88
## 1.9.0 [2020-07-17]
99

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,13 @@ The batching is configurable by ``write_options``\ :
250250
- ``0``
251251
* - **retry_interval**
252252
- the number of milliseconds to retry unsuccessful write. The retry interval is used when the InfluxDB server does not specify "Retry-After" header.
253-
- ``1000``
253+
- ``5000``
254254
* - **max_retries**
255255
- the number of max retries when write fails
256256
- ``3``
257257
* - **max_retry_delay**
258258
- the maximum delay between each retry attempt in milliseconds
259-
- ``15_000``
259+
- ``180_000``
260260

261261

262262
.. code-block:: python

influxdb_client/client/write/retry.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ class WritesRetry(Retry):
1414
:param int max_retry_delay: maximum delay when retrying write
1515
"""
1616

17-
WRITES_RETRY_AFTER_STATUS_CODES = frozenset([429, 503])
18-
19-
def __init__(self, jitter_interval=0, max_retry_delay=15, **kw):
17+
def __init__(self, jitter_interval=0, max_retry_delay=180, **kw):
2018
"""Initialize defaults."""
2119
super().__init__(**kw)
2220
self.jitter_interval = jitter_interval
@@ -35,7 +33,7 @@ def is_retry(self, method, status_code, has_retry_after=False):
3533
if not self._is_method_retryable(method):
3634
return False
3735

38-
return self.total and (status_code in self.WRITES_RETRY_AFTER_STATUS_CODES)
36+
return self.total and (status_code >= 429)
3937

4038
def get_backoff_time(self):
4139
"""Variant of exponential backoff with initial and max delay and a random jitter delay."""
@@ -50,7 +48,7 @@ def get_backoff_time(self):
5048
if consecutive_errors_len < 0:
5149
return 0
5250

53-
backoff_value = self.backoff_factor * (2 ** consecutive_errors_len) + self._jitter_delay()
51+
backoff_value = self.backoff_factor * (5 ** consecutive_errors_len) + self._jitter_delay()
5452
return min(self.max_retry_delay, backoff_value)
5553

5654
def get_retry_after(self, response):

influxdb_client/client/write_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ class WriteOptions(object):
3737
def __init__(self, write_type: WriteType = WriteType.batching,
3838
batch_size=1_000, flush_interval=1_000,
3939
jitter_interval=0,
40-
retry_interval=1_000,
40+
retry_interval=5_000,
4141
max_retries=3,
42-
max_retry_delay=15_000,
42+
max_retry_delay=180_000,
4343
write_scheduler=ThreadPoolScheduler(max_workers=1)) -> None:
4444
"""
4545
Create write api configuration.

tests/test_WriteApiBatching.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,17 @@ def test_jitter_interval(self):
178178
httpretty.httpretty.latest_requests[1].parsed_body)
179179

180180
def test_retry_interval(self):
181+
182+
self._write_client.__del__()
183+
184+
# Set retry interval to 1_500
185+
self.write_options = WriteOptions(batch_size=2, flush_interval=5_000, retry_interval=1_500)
186+
self._write_client = WriteApi(influxdb_client=self.influxdb_client, write_options=self.write_options)
187+
181188
httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=204)
182189
httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=503)
183190
httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=429,
184-
adding_headers={'Retry-After': '5'})
191+
adding_headers={'Retry-After': '3'})
185192
httpretty.register_uri(httpretty.POST, uri="http://localhost/api/v2/write", status=503)
186193

187194
self._write_client.write("my-bucket", "my-org",
@@ -191,14 +198,14 @@ def test_retry_interval(self):
191198
time.sleep(1)
192199
self.assertEqual(1, len(httpretty.httpretty.latest_requests), msg="first request immediately")
193200

194-
time.sleep(3)
201+
time.sleep(1.5)
195202
self.assertEqual(2, len(httpretty.httpretty.latest_requests), msg="second request after delay_interval")
196203

197-
time.sleep(5)
204+
time.sleep(3)
198205
self.assertEqual(3, len(httpretty.httpretty.latest_requests), msg="third request after Retry-After")
199206

200-
time.sleep(12)
201-
self.assertEqual(4, len(httpretty.httpretty.latest_requests), msg="fourth after exponential delay = 3 * 2 * 3")
207+
time.sleep(37.5)
208+
self.assertEqual(4, len(httpretty.httpretty.latest_requests), msg="fourth after exponential delay = 1.5 * 5**2")
202209

203210
self.assertEqual("h2o_feet,location=coyote_creek level\\ water_level=1.0 1\n"
204211
"h2o_feet,location=coyote_creek level\\ water_level=2.0 2",

tests/test_WriteOptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ def test_default(self):
88
retry = WriteOptions().to_retry_strategy()
99

1010
self.assertEqual(retry.total, 3)
11-
self.assertEqual(retry.backoff_factor, 1)
11+
self.assertEqual(retry.backoff_factor, 5)
1212
self.assertEqual(retry.jitter_interval, 0)
13-
self.assertEqual(retry.max_retry_delay, 15)
13+
self.assertEqual(retry.max_retry_delay, 180)
1414
self.assertEqual(retry.method_whitelist, ["POST"])
1515

1616
def test_custom(self):

tests/test_WritesRetry.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def test_copy_jitter(self):
2121
self.assertEqual(retry.total, 8)
2222

2323
def test_backoff(self):
24-
retry = WritesRetry(total=5, backoff_factor=1, max_retry_delay=100)
24+
retry = WritesRetry(total=5, backoff_factor=1, max_retry_delay=550)
2525
self.assertEqual(retry.total, 5)
2626
self.assertEqual(retry.is_exhausted(), False)
2727
self.assertEqual(retry.get_backoff_time(), 0)
@@ -34,22 +34,22 @@ def test_backoff(self):
3434
retry = retry.increment()
3535
self.assertEqual(retry.total, 3)
3636
self.assertEqual(retry.is_exhausted(), False)
37-
self.assertEqual(retry.get_backoff_time(), 2)
37+
self.assertEqual(retry.get_backoff_time(), 5)
3838

3939
retry = retry.increment()
4040
self.assertEqual(retry.total, 2)
4141
self.assertEqual(retry.is_exhausted(), False)
42-
self.assertEqual(retry.get_backoff_time(), 4)
42+
self.assertEqual(retry.get_backoff_time(), 25)
4343

4444
retry = retry.increment()
4545
self.assertEqual(retry.total, 1)
4646
self.assertEqual(retry.is_exhausted(), False)
47-
self.assertEqual(retry.get_backoff_time(), 8)
47+
self.assertEqual(retry.get_backoff_time(), 125)
4848

4949
retry = retry.increment()
5050
self.assertEqual(retry.total, 0)
5151
self.assertEqual(retry.is_exhausted(), False)
52-
self.assertEqual(retry.get_backoff_time(), 16)
52+
self.assertEqual(retry.get_backoff_time(), 550)
5353

5454
with self.assertRaises(MaxRetryError) as cm:
5555
retry.increment()
@@ -98,6 +98,16 @@ def test_is_retry(self):
9898

9999
self.assertTrue(retry.is_retry("POST", 429, True))
100100

101+
def test_is_retry_428(self):
102+
retry = WritesRetry(method_whitelist=["POST"])
103+
104+
self.assertFalse(retry.is_retry("POST", 428, True))
105+
106+
def test_is_retry_430(self):
107+
retry = WritesRetry(method_whitelist=["POST"])
108+
109+
self.assertTrue(retry.is_retry("POST", 430, True))
110+
101111
def test_is_retry_retry_after_header_is_not_required(self):
102112
retry = WritesRetry(method_whitelist=["POST"])
103113

0 commit comments

Comments
 (0)