Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions openfga_sdk/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ def random_time(loop_count, min_wait_in_ms) -> float:
"""
minimum = math.ceil(2**loop_count * min_wait_in_ms)
maximum = math.ceil(2 ** (loop_count + 1) * min_wait_in_ms)
# randrange() raises on an empty range, e.g. when min_wait_in_ms is 0
if maximum <= minimum:
return minimum / 1000
return random.randrange(minimum, maximum) / 1000


Expand Down
6 changes: 5 additions & 1 deletion openfga_sdk/oauth2_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ def jitter(loop_count, min_wait_in_ms):
"""
minimum = math.ceil(2**loop_count * min_wait_in_ms)
maximum = math.ceil(2 ** (loop_count + 1) * min_wait_in_ms)
jitter = random.randrange(minimum, maximum) / 1000
# randrange() raises on an empty range, e.g. when min_wait_in_ms is 0
if maximum <= minimum:
jitter = minimum / 1000
else:
jitter = random.randrange(minimum, maximum) / 1000

# If running in pytest, set jitter to 0 to speed up tests
if "pytest" in sys.modules:
Expand Down
3 changes: 3 additions & 0 deletions openfga_sdk/sync/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ def random_time(loop_count, min_wait_in_ms) -> float:
"""
minimum = math.ceil(2**loop_count * min_wait_in_ms)
maximum = math.ceil(2 ** (loop_count + 1) * min_wait_in_ms)
# randrange() raises on an empty range, e.g. when min_wait_in_ms is 0
if maximum <= minimum:
return minimum / 1000
return random.randrange(minimum, maximum) / 1000


Expand Down
29 changes: 29 additions & 0 deletions test/backoff_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import unittest

from openfga_sdk import api_client
from openfga_sdk.oauth2_common import jitter
from openfga_sdk.sync import api_client as sync_api_client


class TestBackoff(unittest.TestCase):
"""The retry wait helpers accept a minimum wait of 0"""

def test_random_time_with_zero_min_wait(self):
for loop_count in range(3):
self.assertEqual(api_client.random_time(loop_count, 0), 0)
self.assertEqual(sync_api_client.random_time(loop_count, 0), 0)

def test_random_time_stays_in_range(self):
for loop_count in range(3):
for random_time in (api_client.random_time, sync_api_client.random_time):
wait = random_time(loop_count, 100)
self.assertGreaterEqual(wait, 2**loop_count * 100 / 1000)
self.assertLess(wait, 2 ** (loop_count + 1) * 100 / 1000)

def test_jitter_with_zero_min_wait(self):
for loop_count in range(3):
self.assertEqual(jitter(loop_count, 0), 0)


if __name__ == "__main__":
unittest.main()