Skip to content

Commit ea6d781

Browse files
committed
fix backoff constants and test
1 parent 5b9dbe3 commit ea6d781

File tree

4 files changed

+36
-54
lines changed

4 files changed

+36
-54
lines changed

pymongo/asynchronous/client_session.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ def _max_time_expired_error(exc: PyMongoError) -> bool:
474474
# default value of MongoDB's `transactionLifetimeLimitSeconds` parameter.
475475
_WITH_TRANSACTION_RETRY_TIME_LIMIT = 120
476476
_BACKOFF_MAX = 0.500 # 500ms max backoff
477-
_BACKOFF_INITIAL = 0.001 # 1ms initial backoff
477+
_BACKOFF_INITIAL = 0.005 # 5ms initial backoff
478478

479479

480480
def _set_backoff_initial(seconds: float) -> None:
@@ -719,7 +719,7 @@ async def callback(session, custom_arg, custom_kwarg=None):
719719
while True:
720720
if retry: # Implement exponential backoff on retry.
721721
jitter = random.random() # noqa: S311
722-
backoff = jitter * min(_BACKOFF_INITIAL * (1.25**retry), _BACKOFF_MAX)
722+
backoff = jitter * min(_BACKOFF_INITIAL * (1.5**retry), _BACKOFF_MAX)
723723
if _would_exceed_time_limit(start_time, backoff):
724724
assert last_error is not None
725725
raise last_error

pymongo/synchronous/client_session.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ def _max_time_expired_error(exc: PyMongoError) -> bool:
472472
# default value of MongoDB's `transactionLifetimeLimitSeconds` parameter.
473473
_WITH_TRANSACTION_RETRY_TIME_LIMIT = 120
474474
_BACKOFF_MAX = 0.500 # 500ms max backoff
475-
_BACKOFF_INITIAL = 0.001 # 1ms initial backoff
475+
_BACKOFF_INITIAL = 0.005 # 5ms initial backoff
476476

477477

478478
def _set_backoff_initial(seconds: float) -> None:
@@ -717,7 +717,7 @@ def callback(session, custom_arg, custom_kwarg=None):
717717
while True:
718718
if retry: # Implement exponential backoff on retry.
719719
jitter = random.random() # noqa: S311
720-
backoff = jitter * min(_BACKOFF_INITIAL * (1.25**retry), _BACKOFF_MAX)
720+
backoff = jitter * min(_BACKOFF_INITIAL * (1.5**retry), _BACKOFF_MAX)
721721
if _would_exceed_time_limit(start_time, backoff):
722722
assert last_error is not None
723723
raise last_error

test/asynchronous/test_transactions.py

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -610,15 +610,25 @@ async def callback(session):
610610

611611
@async_client_context.require_test_commands
612612
@async_client_context.require_transactions
613-
async def test_transaction_backoff_is_random(self):
613+
async def test_transaction_backoff(self):
614614
client = async_client_context.client
615615
coll = client[self.db.name].test
616+
# patch random to make it deterministic
617+
_original_random_random = random.random
618+
619+
def always_one():
620+
return 1
621+
622+
def always_zero():
623+
return 0
624+
625+
random.random = always_zero
616626
# set fail point to trigger transaction failure and trigger backoff
617627
await self.set_fail_point(
618628
{
619629
"configureFailPoint": "failCommand",
620630
"mode": {
621-
"times": 30
631+
"times": 13
622632
}, # sufficiently high enough such that the time effect of backoff is noticeable
623633
"data": {
624634
"failCommands": ["commitTransaction"],
@@ -630,35 +640,22 @@ async def test_transaction_backoff_is_random(self):
630640
self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"}
631641
)
632642

633-
start = time.monotonic()
634-
635643
async def callback(session):
636644
await coll.insert_one({}, session=session)
637645

646+
start = time.monotonic()
638647
async with self.client.start_session() as s:
639648
await s.with_transaction(callback)
640-
641649
end = time.monotonic()
642-
self.assertLess(end - start, 3.5) # sum of 30 backoffs are 3.5629515313825695
643-
644-
@async_client_context.require_test_commands
645-
@async_client_context.require_transactions
646-
async def test_transaction_backoff(self):
647-
client = async_client_context.client
648-
coll = client[self.db.name].test
649-
# patch random to make it deterministic
650-
_original_random_random = random.random
651-
652-
def always_one():
653-
return 1
650+
no_backoff_time = end - start
654651

655652
random.random = always_one
656653
# set fail point to trigger transaction failure and trigger backoff
657654
await self.set_fail_point(
658655
{
659656
"configureFailPoint": "failCommand",
660657
"mode": {
661-
"times": 30
658+
"times": 13
662659
}, # sufficiently high enough such that the time effect of backoff is noticeable
663660
"data": {
664661
"failCommands": ["commitTransaction"],
@@ -669,17 +666,11 @@ def always_one():
669666
self.addAsyncCleanup(
670667
self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"}
671668
)
672-
673669
start = time.monotonic()
674-
675-
async def callback(session):
676-
await coll.insert_one({}, session=session)
677-
678670
async with self.client.start_session() as s:
679671
await s.with_transaction(callback)
680-
681672
end = time.monotonic()
682-
self.assertGreaterEqual(end - start, 3.5) # sum of 30 backoffs are 3.5629515313825695
673+
self.assertLess(abs(end - start - (no_backoff_time + 2.2)), 1) # sum of 13 backoffs is 2.2
683674

684675
random.random = _original_random_random
685676

test/test_transactions.py

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -598,15 +598,25 @@ def callback(session):
598598

599599
@client_context.require_test_commands
600600
@client_context.require_transactions
601-
def test_transaction_backoff_is_random(self):
601+
def test_transaction_backoff(self):
602602
client = client_context.client
603603
coll = client[self.db.name].test
604+
# patch random to make it deterministic
605+
_original_random_random = random.random
606+
607+
def always_one():
608+
return 1
609+
610+
def always_zero():
611+
return 0
612+
613+
random.random = always_zero
604614
# set fail point to trigger transaction failure and trigger backoff
605615
self.set_fail_point(
606616
{
607617
"configureFailPoint": "failCommand",
608618
"mode": {
609-
"times": 30
619+
"times": 13
610620
}, # sufficiently high enough such that the time effect of backoff is noticeable
611621
"data": {
612622
"failCommands": ["commitTransaction"],
@@ -616,35 +626,22 @@ def test_transaction_backoff_is_random(self):
616626
)
617627
self.addCleanup(self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"})
618628

619-
start = time.monotonic()
620-
621629
def callback(session):
622630
coll.insert_one({}, session=session)
623631

632+
start = time.monotonic()
624633
with self.client.start_session() as s:
625634
s.with_transaction(callback)
626-
627635
end = time.monotonic()
628-
self.assertLess(end - start, 3.5) # sum of 30 backoffs are 3.5629515313825695
629-
630-
@client_context.require_test_commands
631-
@client_context.require_transactions
632-
def test_transaction_backoff(self):
633-
client = client_context.client
634-
coll = client[self.db.name].test
635-
# patch random to make it deterministic
636-
_original_random_random = random.random
637-
638-
def always_one():
639-
return 1
636+
no_backoff_time = end - start
640637

641638
random.random = always_one
642639
# set fail point to trigger transaction failure and trigger backoff
643640
self.set_fail_point(
644641
{
645642
"configureFailPoint": "failCommand",
646643
"mode": {
647-
"times": 30
644+
"times": 13
648645
}, # sufficiently high enough such that the time effect of backoff is noticeable
649646
"data": {
650647
"failCommands": ["commitTransaction"],
@@ -653,17 +650,11 @@ def always_one():
653650
}
654651
)
655652
self.addCleanup(self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"})
656-
657653
start = time.monotonic()
658-
659-
def callback(session):
660-
coll.insert_one({}, session=session)
661-
662654
with self.client.start_session() as s:
663655
s.with_transaction(callback)
664-
665656
end = time.monotonic()
666-
self.assertGreaterEqual(end - start, 3.5) # sum of 30 backoffs are 3.5629515313825695
657+
self.assertLess(abs(end - start - (no_backoff_time + 2.2)), 1) # sum of 13 backoffs is 2.2
667658

668659
random.random = _original_random_random
669660

0 commit comments

Comments
 (0)