Skip to content

Commit a6ae852

Browse files
authored
PYTHON-3290 Nested pymongo.timeout() calls only shorten the deadline (#966)
1 parent 77ace9a commit a6ae852

File tree

3 files changed

+9
-7
lines changed

3 files changed

+9
-7
lines changed

pymongo/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,17 @@ def timeout(seconds: Optional[float]) -> ContextManager:
127127
NetworkTimeout) as exc:
128128
print(f"block timed out: {exc!r}")
129129
130-
When nesting :func:`~pymongo.timeout`, the nested block overrides the
131-
timeout. When exiting the block, the previous deadline is restored::
130+
When nesting :func:`~pymongo.timeout`, the newly computed deadline is capped to at most
131+
the existing deadline. The deadline can only be shortened, not extended.
132+
When exiting the block, the previous deadline is restored::
132133
133134
with pymongo.timeout(5):
134135
coll.find_one() # Uses the 5 second deadline.
135136
with pymongo.timeout(3):
136137
coll.find_one() # Uses the 3 second deadline.
137138
coll.find_one() # Uses the original 5 second deadline.
138139
with pymongo.timeout(10):
139-
coll.find_one() # Uses the 10 second deadline.
140+
coll.find_one() # Still uses the original 5 second deadline.
140141
coll.find_one() # Uses the original 5 second deadline.
141142
142143
:Parameters:

pymongo/_csot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ def __init__(self, timeout: Optional[float]):
7070

7171
def __enter__(self):
7272
timeout_token = TIMEOUT.set(self._timeout)
73-
deadline_token = DEADLINE.set(
74-
time.monotonic() + self._timeout if self._timeout else float("inf")
75-
)
73+
prev_deadline = DEADLINE.get()
74+
next_deadline = time.monotonic() + self._timeout if self._timeout else float("inf")
75+
deadline_token = DEADLINE.set(min(prev_deadline, next_deadline))
7676
rtt_token = RTT.set(0.0)
7777
self._tokens = (timeout_token, deadline_token, rtt_token)
7878
return self

test/test_csot.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ def test_timeout_nested(self):
4343
self.assertEqual(_csot.get_timeout(), 10)
4444
deadline_10 = _csot.get_deadline()
4545

46+
# Capped at the original 10 deadline.
4647
with pymongo.timeout(15):
4748
coll.find_one()
4849
self.assertEqual(_csot.get_timeout(), 15)
49-
self.assertGreater(_csot.get_deadline(), deadline_10)
50+
self.assertEqual(_csot.get_deadline(), deadline_10)
5051

5152
# Should be reset to previous values
5253
self.assertEqual(_csot.get_timeout(), 10)

0 commit comments

Comments
 (0)