|
47 | 47 | if TYPE_CHECKING:
|
48 | 48 | from pymongo.cursor_shared import _Hint
|
49 | 49 | from pymongo.operations import _IndexList
|
| 50 | + from pymongo.pool_options import PoolOptions |
50 | 51 | from pymongo.typings import _DocumentOut
|
51 | 52 |
|
52 | 53 |
|
|
108 | 109 | }
|
109 | 110 |
|
110 | 111 |
|
| 112 | +def _get_timeout_details(options: PoolOptions) -> dict[str, float]: |
| 113 | + from pymongo import _csot |
| 114 | + |
| 115 | + details = {} |
| 116 | + timeout = _csot.get_timeout() |
| 117 | + socket_timeout = options.socket_timeout |
| 118 | + connect_timeout = options.connect_timeout |
| 119 | + if timeout: |
| 120 | + details["timeoutMS"] = timeout * 1000 |
| 121 | + if socket_timeout and not timeout: |
| 122 | + details["socketTimeoutMS"] = socket_timeout * 1000 |
| 123 | + if connect_timeout: |
| 124 | + details["connectTimeoutMS"] = connect_timeout * 1000 |
| 125 | + return details |
| 126 | + |
| 127 | + |
| 128 | +def format_timeout_details(details: Optional[dict[str, float]]) -> str: |
| 129 | + result = "" |
| 130 | + if details: |
| 131 | + result += " (configured timeouts:" |
| 132 | + for timeout in ["socketTimeoutMS", "timeoutMS", "connectTimeoutMS"]: |
| 133 | + if timeout in details: |
| 134 | + result += f" {timeout}: {details[timeout]}ms," |
| 135 | + result = result[:-1] |
| 136 | + result += ")" |
| 137 | + return result |
| 138 | + |
| 139 | + |
111 | 140 | def _gen_index_name(keys: _IndexList) -> str:
|
112 | 141 | """Generate an index name from the set of fields it is over."""
|
113 | 142 | return "_".join(["{}_{}".format(*item) for item in keys])
|
@@ -188,6 +217,7 @@ def _check_command_response(
|
188 | 217 | max_wire_version: Optional[int],
|
189 | 218 | allowable_errors: Optional[Container[Union[int, str]]] = None,
|
190 | 219 | parse_write_concern_error: bool = False,
|
| 220 | + pool_opts: Optional[PoolOptions] = None, |
191 | 221 | ) -> None:
|
192 | 222 | """Check the response to a command for errors."""
|
193 | 223 | if "ok" not in response:
|
@@ -243,6 +273,10 @@ def _check_command_response(
|
243 | 273 | if code in (11000, 11001, 12582):
|
244 | 274 | raise DuplicateKeyError(errmsg, code, response, max_wire_version)
|
245 | 275 | elif code == 50:
|
| 276 | + # Append timeout details to MaxTimeMSExpired responses. |
| 277 | + if pool_opts: |
| 278 | + timeout_details = _get_timeout_details(pool_opts) |
| 279 | + errmsg += format_timeout_details(timeout_details) |
246 | 280 | raise ExecutionTimeout(errmsg, code, response, max_wire_version)
|
247 | 281 | elif code == 43:
|
248 | 282 | raise CursorNotFound(errmsg, code, response, max_wire_version)
|
|
0 commit comments