Skip to content

Commit 782aa2a

Browse files
committed
fix backoff constants and test
1 parent 678c66f commit 782aa2a

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
@@ -473,7 +473,7 @@ def _max_time_expired_error(exc: PyMongoError) -> bool:
473473
# default value of MongoDB's `transactionLifetimeLimitSeconds` parameter.
474474
_WITH_TRANSACTION_RETRY_TIME_LIMIT = 120
475475
_BACKOFF_MAX = 0.500 # 500ms max backoff
476-
_BACKOFF_INITIAL = 0.001 # 1ms initial backoff
476+
_BACKOFF_INITIAL = 0.005 # 5ms initial backoff
477477

478478

479479
def _within_time_limit(start_time: float) -> bool:
@@ -717,7 +717,7 @@ async 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

pymongo/synchronous/client_session.py

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

476476

477477
def _within_time_limit(start_time: float) -> bool:
@@ -715,7 +715,7 @@ def callback(session, custom_arg, custom_kwarg=None):
715715
while True:
716716
if retry: # Implement exponential backoff on retry.
717717
jitter = random.random() # noqa: S311
718-
backoff = jitter * min(_BACKOFF_INITIAL * (1.25**retry), _BACKOFF_MAX)
718+
backoff = jitter * min(_BACKOFF_INITIAL * (1.5**retry), _BACKOFF_MAX)
719719
if _would_exceed_time_limit(start_time, backoff):
720720
assert last_error is not None
721721
raise last_error

test/asynchronous/test_transactions.py

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

623623
@async_client_context.require_test_commands
624624
@async_client_context.require_transactions
625-
async def test_transaction_backoff_is_random(self):
625+
async def test_transaction_backoff(self):
626626
client = async_client_context.client
627627
coll = client[self.db.name].test
628+
# patch random to make it deterministic
629+
_original_random_random = random.random
630+
631+
def always_one():
632+
return 1
633+
634+
def always_zero():
635+
return 0
636+
637+
random.random = always_zero
628638
# set fail point to trigger transaction failure and trigger backoff
629639
await self.set_fail_point(
630640
{
631641
"configureFailPoint": "failCommand",
632642
"mode": {
633-
"times": 30
643+
"times": 13
634644
}, # sufficiently high enough such that the time effect of backoff is noticeable
635645
"data": {
636646
"failCommands": ["commitTransaction"],
@@ -642,35 +652,22 @@ async def test_transaction_backoff_is_random(self):
642652
self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"}
643653
)
644654

645-
start = time.monotonic()
646-
647655
async def callback(session):
648656
await coll.insert_one({}, session=session)
649657

658+
start = time.monotonic()
650659
async with self.client.start_session() as s:
651660
await s.with_transaction(callback)
652-
653661
end = time.monotonic()
654-
self.assertLess(end - start, 3.5) # sum of 30 backoffs are 3.5629515313825695
655-
656-
@async_client_context.require_test_commands
657-
@async_client_context.require_transactions
658-
async def test_transaction_backoff(self):
659-
client = async_client_context.client
660-
coll = client[self.db.name].test
661-
# patch random to make it deterministic
662-
_original_random_random = random.random
663-
664-
def always_one():
665-
return 1
662+
no_backoff_time = end - start
666663

667664
random.random = always_one
668665
# set fail point to trigger transaction failure and trigger backoff
669666
await self.set_fail_point(
670667
{
671668
"configureFailPoint": "failCommand",
672669
"mode": {
673-
"times": 30
670+
"times": 13
674671
}, # sufficiently high enough such that the time effect of backoff is noticeable
675672
"data": {
676673
"failCommands": ["commitTransaction"],
@@ -681,17 +678,11 @@ def always_one():
681678
self.addAsyncCleanup(
682679
self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"}
683680
)
684-
685681
start = time.monotonic()
686-
687-
async def callback(session):
688-
await coll.insert_one({}, session=session)
689-
690682
async with self.client.start_session() as s:
691683
await s.with_transaction(callback)
692-
693684
end = time.monotonic()
694-
self.assertGreaterEqual(end - start, 3.5) # sum of 30 backoffs are 3.5629515313825695
685+
self.assertLess(abs(end - start - (no_backoff_time + 2.2)), 1) # sum of 13 backoffs is 2.2
695686

696687
random.random = _original_random_random
697688

test/test_transactions.py

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

611611
@client_context.require_test_commands
612612
@client_context.require_transactions
613-
def test_transaction_backoff_is_random(self):
613+
def test_transaction_backoff(self):
614614
client = 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
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"],
@@ -628,35 +638,22 @@ def test_transaction_backoff_is_random(self):
628638
)
629639
self.addCleanup(self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"})
630640

631-
start = time.monotonic()
632-
633641
def callback(session):
634642
coll.insert_one({}, session=session)
635643

644+
start = time.monotonic()
636645
with self.client.start_session() as s:
637646
s.with_transaction(callback)
638-
639647
end = time.monotonic()
640-
self.assertLess(end - start, 3.5) # sum of 30 backoffs are 3.5629515313825695
641-
642-
@client_context.require_test_commands
643-
@client_context.require_transactions
644-
def test_transaction_backoff(self):
645-
client = client_context.client
646-
coll = client[self.db.name].test
647-
# patch random to make it deterministic
648-
_original_random_random = random.random
649-
650-
def always_one():
651-
return 1
648+
no_backoff_time = end - start
652649

653650
random.random = always_one
654651
# set fail point to trigger transaction failure and trigger backoff
655652
self.set_fail_point(
656653
{
657654
"configureFailPoint": "failCommand",
658655
"mode": {
659-
"times": 30
656+
"times": 13
660657
}, # sufficiently high enough such that the time effect of backoff is noticeable
661658
"data": {
662659
"failCommands": ["commitTransaction"],
@@ -665,17 +662,11 @@ def always_one():
665662
}
666663
)
667664
self.addCleanup(self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"})
668-
669665
start = time.monotonic()
670-
671-
def callback(session):
672-
coll.insert_one({}, session=session)
673-
674666
with self.client.start_session() as s:
675667
s.with_transaction(callback)
676-
677668
end = time.monotonic()
678-
self.assertGreaterEqual(end - start, 3.5) # sum of 30 backoffs are 3.5629515313825695
669+
self.assertLess(abs(end - start - (no_backoff_time + 2.2)), 1) # sum of 13 backoffs is 2.2
679670

680671
random.random = _original_random_random
681672

0 commit comments

Comments
 (0)