Skip to content

Commit c106c08

Browse files
authored
PYTHON-3295 Add CSOT docs page (#1111)
1 parent bcb0ac0 commit c106c08

File tree

5 files changed

+169
-2
lines changed

5 files changed

+169
-2
lines changed

doc/changelog.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Version 4.3.3 fixes a number of bugs:
1111
instead of line by line (`PYTHON-3502`_).
1212
- Improved performance of :meth:`gridfs.grid_file.GridOut.read` and
1313
:meth:`gridfs.grid_file.GridOut.readline` (`PYTHON-3508`_).
14+
- Added the :ref:`timeout-example` example page to improve the documentation
15+
for :func:`pymongo.timeout`.
1416

1517
Issues Resolved
1618
...............
@@ -90,7 +92,7 @@ PyMongo 4.2 brings a number of improvements including:
9092
- Support for the Queryable Encryption beta with MongoDB 6.0. Note that backwards-breaking
9193
changes may be made before the final release. See :ref:`automatic-queryable-client-side-encryption` for example usage.
9294
- Provisional (beta) support for :func:`pymongo.timeout` to apply a single timeout
93-
to an entire block of pymongo operations.
95+
to an entire block of pymongo operations. See :ref:`timeout-example` for examples.
9496
- Added the ``timeoutMS`` URI and keyword argument to :class:`~pymongo.mongo_client.MongoClient`.
9597
- Added the :attr:`pymongo.errors.PyMongoError.timeout` property which is ``True`` when
9698
the error was caused by a timeout.

doc/examples/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ MongoDB, you can start it like so:
3030
mod_wsgi
3131
server_selection
3232
tailable
33+
timeouts
3334
tls
3435
type_hints
3536
encryption

doc/examples/timeouts.rst

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
2+
.. _timeout-example:
3+
4+
Client Side Operation Timeout
5+
=============================
6+
7+
PyMongo 4.2 introduced :meth:`~pymongo.timeout` and the ``timeoutMS``
8+
URI and keyword argument to :class:`~pymongo.mongo_client.MongoClient`.
9+
These features allow applications to more easily limit the amount of time that
10+
one or more operations can execute before control is returned to the app. This
11+
timeout applies to all of the work done to execute the operation, including
12+
but not limited to server selection, connection checkout, serialization, and
13+
server-side execution.
14+
15+
Basic Usage
16+
-----------
17+
18+
The following example uses :meth:`~pymongo.timeout` to configure a 10-second
19+
timeout for an :meth:`~pymongo.collection.Collection.insert_one` operation::
20+
21+
import pymongo
22+
with pymongo.timeout(10):
23+
coll.insert_one({"name": "Nunu"})
24+
25+
The :meth:`~pymongo.timeout` applies to all pymongo operations within the block.
26+
The following example ensures that both the `insert` and the `find` complete
27+
within 10 seconds total, or raise a timeout error::
28+
29+
with pymongo.timeout(10):
30+
coll.insert_one({"name": "Nunu"})
31+
coll.find_one({"name": "Nunu"})
32+
33+
When nesting :func:`~pymongo.timeout`, the nested deadline is capped by the outer
34+
deadline. The deadline can only be shortened, not extended.
35+
When exiting the block, the previous deadline is restored::
36+
37+
with pymongo.timeout(5):
38+
coll.find_one() # Uses the 5 second deadline.
39+
with pymongo.timeout(3):
40+
coll.find_one() # Uses the 3 second deadline.
41+
coll.find_one() # Uses the original 5 second deadline.
42+
with pymongo.timeout(10):
43+
coll.find_one() # Still uses the original 5 second deadline.
44+
coll.find_one() # Uses the original 5 second deadline.
45+
46+
Timeout errors
47+
--------------
48+
49+
When the :meth:`~pymongo.timeout` with-statement is entered, a deadline is set
50+
for the entire block. When that deadline is exceeded, any blocking pymongo operation
51+
will raise a timeout exception. For example::
52+
53+
try:
54+
with pymongo.timeout(10):
55+
coll.insert_one({"name": "Nunu"})
56+
time.sleep(10)
57+
# The deadline has now expired, the next operation will raise
58+
# a timeout exception.
59+
coll.find_one({"name": "Nunu"})
60+
except PyMongoError as exc:
61+
if exc.timeout:
62+
print(f"block timed out: {exc!r}")
63+
else:
64+
print(f"failed with non-timeout error: {exc!r}")
65+
66+
The :attr:`pymongo.errors.PyMongoError.timeout` property (added in PyMongo 4.2)
67+
will be ``True`` when the error was caused by a timeout and ``False`` otherwise.
68+
69+
The timeoutMS URI option
70+
------------------------
71+
72+
PyMongo 4.2 also added support for the ``timeoutMS`` URI and keyword argument to
73+
:class:`~pymongo.mongo_client.MongoClient`. When this option is configured, the
74+
client will automatically apply the timeout to each API call. For example::
75+
76+
client = MongoClient("mongodb://localhost/?timeoutMS=10000")
77+
coll = client.test.test
78+
coll.insert_one({"name": "Nunu"}) # Uses a 10-second timeout.
79+
coll.find_one({"name": "Nunu"}) # Also uses a 10-second timeout.
80+
81+
The above is roughly equivalent to::
82+
83+
client = MongoClient()
84+
coll = client.test.test
85+
with pymongo.timeout(10):
86+
coll.insert_one({"name": "Nunu"})
87+
with pymongo.timeout(10):
88+
coll.find_one({"name": "Nunu"})
89+
90+
pymongo.timeout overrides timeoutMS
91+
-----------------------------------
92+
93+
:meth:`~pymongo.timeout` overrides ``timeoutMS``; within a
94+
:meth:`~pymongo.timeout` block a client's ``timeoutMS`` option is ignored::
95+
96+
client = MongoClient("mongodb://localhost/?timeoutMS=10000")
97+
coll = client.test.test
98+
coll.insert_one({"name": "Nunu"}) # Uses the client's 10-second timeout.
99+
# pymongo.timeout overrides the client's timeoutMS.
100+
with pymongo.timeout(20):
101+
coll.insert_one({"name": "Nunu"}) # Uses the 20-second timeout.
102+
with pymongo.timeout(5):
103+
coll.find_one({"name": "Nunu"}) # Uses the 5-second timeout.
104+
105+
pymongo.timeout is thread safe
106+
------------------------------
107+
108+
:meth:`~pymongo.timeout` is thread safe; the timeout only applies to current
109+
thread and multiple threads can configure different timeouts in parallel.
110+
111+
pymongo.timeout is asyncio safe
112+
-------------------------------
113+
114+
:meth:`~pymongo.timeout` is asyncio safe; the timeout only applies to current
115+
Task and multiple Tasks can configure different timeouts concurrently.
116+
:meth:`~pymongo.timeout` can be used identically in
117+
`Motor <https://github.com/mongodb/motor>`_, for example::
118+
119+
import motor.motor_asyncio
120+
client = motor.motor_asyncio.AsyncIOMotorClient()
121+
coll = client.test.test
122+
with pymongo.timeout(10):
123+
await coll.insert_one({"name": "Nunu"})
124+
await coll.find_one({"name": "Nunu"})
125+
126+
Troubleshooting
127+
---------------
128+
129+
There are many timeout errors that can be raised depending on when the timeout
130+
expires. In code, these can be identified with the :attr:`pymongo.errors.PyMongoError.timeout`
131+
property. Some specific timeout errors examples are described below.
132+
133+
When the client was unable to find an available server to run the operation
134+
within the given timeout::
135+
136+
pymongo.errors.ServerSelectionTimeoutError: No servers found yet, Timeout: -0.00202266700216569s, Topology Description: <TopologyDescription id: 63698e87cebfd22ab1bd2ae0, topology_type: Unknown, servers: [<ServerDescription ('localhost', 27017) server_type: Unknown, rtt: None>]>
137+
138+
When either the client was unable to establish a connection within the given
139+
timeout or the operation was sent but the server was not able to respond in time::
140+
141+
pymongo.errors.NetworkTimeout: localhost:27017: timed out
142+
143+
When the server cancelled the operation because it exceeded the given timeout.
144+
Note that the operation may have partially completed on the server (depending
145+
on the operation)::
146+
147+
pymongo.errors.ExecutionTimeout: operation exceeded time limit, full error: {'ok': 0.0, 'errmsg': 'operation exceeded time limit', 'code': 50, 'codeName': 'MaxTimeMSExpired'}
148+
149+
When the client cancelled the operation because it was not possible to complete
150+
within the given timeout::
151+
152+
pymongo.errors.ExecutionTimeout: operation would exceed time limit, remaining timeout:0.00196 <= network round trip time:0.00427
153+
154+
When the client attempted a write operation but the server could not replicate
155+
that write (according to the configured write concern) within the given timeout::
156+
157+
pymongo.errors.WTimeoutError: operation exceeded time limit, full error: {'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}
158+
159+
The same error as above but for :meth:`~pymongo.collection.Collection.insert_many`
160+
or :meth:`~pymongo.collection.Collection.bulk_write`::
161+
162+
pymongo.errors.BulkWriteError: batch op errors occurred, full error: {'writeErrors': [], 'writeConcernErrors': [{'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 0, 'nModified': 0, 'nRemoved': 0, 'upserted': []}

doc/examples/type_hints.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
.. _type_hints-example:
33

44
Type Hints
5-
===========
5+
==========
66

77
As of version 4.1, PyMongo ships with `type hints`_. With type hints, Python
88
type checkers can easily find bugs before they reveal themselves in your code.

pymongo/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ def timeout(seconds: Optional[float]) -> ContextManager:
161161
:Raises:
162162
- :py:class:`ValueError`: When `seconds` is negative.
163163
164+
See :ref:`timeout-example` for more examples.
165+
164166
.. versionadded:: 4.2
165167
"""
166168
if not isinstance(seconds, (int, float, type(None))):

0 commit comments

Comments
 (0)