Skip to content

Commit 071626f

Browse files
committed
update error behavior and add tests for server description changed
1 parent 05b4984 commit 071626f

File tree

5 files changed

+61
-38
lines changed

5 files changed

+61
-38
lines changed

pymongo/asynchronous/pool.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,12 +1022,9 @@ async def remove_stale_sockets(self, reference_generation: int) -> None:
10221022
self.requests -= 1
10231023
self.size_cond.notify()
10241024

1025-
def _handle_connection_error(self, error: BaseException, phase: str, conn_id: int) -> None:
1025+
def _handle_connection_error(self, error: BaseException) -> None:
10261026
# Handle system overload condition for non-sdam pools.
1027-
# Look for an AutoReconnect error raised from a ConnectionResetError with
1028-
# errno == errno.ECONNRESET or raised from an OSError that we've created due to
1029-
# a closed connection.
1030-
# If found, add error labels.
1027+
# Look for errors of type AutoReconnect and add error labels if appropriate.
10311028
if self.is_sdam or type(error) != AutoReconnect:
10321029
return
10331030
error._add_error_label("SystemOverloadedError")
@@ -1062,13 +1059,8 @@ async def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> A
10621059
driverConnectionId=conn_id,
10631060
)
10641061

1065-
# Pass a context to determine if we successfully create a configured socket.
1066-
context = dict(has_created_socket=False)
1067-
10681062
try:
1069-
networking_interface = await _configured_protocol_interface(
1070-
self.address, self.opts, context=context
1071-
)
1063+
networking_interface = await _configured_protocol_interface(self.address, self.opts)
10721064
# Catch KeyboardInterrupt, CancelledError, etc. and cleanup.
10731065
except BaseException as error:
10741066
async with self.lock:
@@ -1089,8 +1081,7 @@ async def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> A
10891081
reason=_verbose_connection_error_reason(ConnectionClosedReason.ERROR),
10901082
error=ConnectionClosedReason.ERROR,
10911083
)
1092-
if context["has_created_socket"]:
1093-
self._handle_connection_error(error, "handshake", conn_id)
1084+
self._handle_connection_error(error)
10941085
if isinstance(error, (IOError, OSError, *SSLErrors)):
10951086
details = _get_timeout_details(self.opts)
10961087
_raise_connection_failure(self.address, error, timeout_details=details)
@@ -1117,7 +1108,7 @@ async def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> A
11171108
async with self.lock:
11181109
self.active_contexts.discard(conn.cancel_context)
11191110
if not completed_hello:
1120-
self._handle_connection_error(e, "hello", conn_id)
1111+
self._handle_connection_error(e)
11211112
await conn.close_conn(ConnectionClosedReason.ERROR)
11221113
raise
11231114

pymongo/pool_shared.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ async def _configured_protocol_interface(
250250
address: _Address,
251251
options: PoolOptions,
252252
protocol_kls: type[PyMongoBaseProtocol] = PyMongoProtocol,
253-
context: dict[str, bool] | None = None,
254253
) -> AsyncNetworkingInterface:
255254
"""Given (host, port) and PoolOptions, return a configured AsyncNetworkingInterface.
256255
@@ -262,10 +261,6 @@ async def _configured_protocol_interface(
262261
ssl_context = options._ssl_context
263262
timeout = options.socket_timeout
264263

265-
# Signal that we have created the socket successfully.
266-
if context:
267-
context["has_created_socket"] = True
268-
269264
if ssl_context is None:
270265
return AsyncNetworkingInterface(
271266
await asyncio.get_running_loop().create_connection(
@@ -379,7 +374,7 @@ def _create_connection(address: _Address, options: PoolOptions) -> socket.socket
379374

380375

381376
def _configured_socket_interface(
382-
address: _Address, options: PoolOptions, *args: Any, context: dict[str, bool] | None = None
377+
address: _Address, options: PoolOptions, *args: Any
383378
) -> NetworkingInterface:
384379
"""Given (host, port) and PoolOptions, return a NetworkingInterface wrapping a configured socket.
385380
@@ -390,10 +385,6 @@ def _configured_socket_interface(
390385
sock = _create_connection(address, options)
391386
ssl_context = options._ssl_context
392387

393-
# Signal that we have created the socket successfully.
394-
if context:
395-
context["has_created_socket"] = True
396-
397388
if ssl_context is None:
398389
sock.settimeout(options.socket_timeout)
399390
return NetworkingInterface(sock)

pymongo/synchronous/pool.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,12 +1018,9 @@ def remove_stale_sockets(self, reference_generation: int) -> None:
10181018
self.requests -= 1
10191019
self.size_cond.notify()
10201020

1021-
def _handle_connection_error(self, error: BaseException, phase: str, conn_id: int) -> None:
1021+
def _handle_connection_error(self, error: BaseException) -> None:
10221022
# Handle system overload condition for non-sdam pools.
1023-
# Look for an AutoReconnect error raised from a ConnectionResetError with
1024-
# errno == errno.ECONNRESET or raised from an OSError that we've created due to
1025-
# a closed connection.
1026-
# If found, add error labels.
1023+
# Look for errors of type AutoReconnect and add error labels if appropriate.
10271024
if self.is_sdam or type(error) != AutoReconnect:
10281025
return
10291026
error._add_error_label("SystemOverloadedError")
@@ -1058,13 +1055,8 @@ def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> Connect
10581055
driverConnectionId=conn_id,
10591056
)
10601057

1061-
# Pass a context to determine if we successfully create a configured socket.
1062-
context = dict(has_created_socket=False)
1063-
10641058
try:
1065-
networking_interface = _configured_socket_interface(
1066-
self.address, self.opts, context=context
1067-
)
1059+
networking_interface = _configured_socket_interface(self.address, self.opts)
10681060
# Catch KeyboardInterrupt, CancelledError, etc. and cleanup.
10691061
except BaseException as error:
10701062
with self.lock:
@@ -1085,8 +1077,7 @@ def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> Connect
10851077
reason=_verbose_connection_error_reason(ConnectionClosedReason.ERROR),
10861078
error=ConnectionClosedReason.ERROR,
10871079
)
1088-
if context["has_created_socket"]:
1089-
self._handle_connection_error(error, "handshake", conn_id)
1080+
self._handle_connection_error(error)
10901081
if isinstance(error, (IOError, OSError, *SSLErrors)):
10911082
details = _get_timeout_details(self.opts)
10921083
_raise_connection_failure(self.address, error, timeout_details=details)
@@ -1113,7 +1104,7 @@ def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> Connect
11131104
with self.lock:
11141105
self.active_contexts.discard(conn.cancel_context)
11151106
if not completed_hello:
1116-
self._handle_connection_error(e, "hello", conn_id)
1107+
self._handle_connection_error(e)
11171108
conn.close_conn(ConnectionClosedReason.ERROR)
11181109
raise
11191110

test/discovery_and_monitoring/unified/backpressure-network-error-fail.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"useMultipleMongoses": false,
5050
"observeEvents": [
5151
"serverHeartbeatSucceededEvent",
52+
"serverDescriptionChangedEvent",
5253
"poolReadyEvent",
5354
"poolClearedEvent"
5455
],
@@ -89,6 +90,17 @@
8990
"count": 1
9091
}
9192
},
93+
{
94+
"name": "waitForEvent",
95+
"object": "testRunner",
96+
"arguments": {
97+
"client": "client",
98+
"event": {
99+
"serverDescriptionChangedEvent": {}
100+
},
101+
"count": 1
102+
}
103+
},
92104
{
93105
"name": "failPoint",
94106
"object": "testRunner",
@@ -139,6 +151,19 @@
139151
"poolReadyEvent": {}
140152
}
141153
]
154+
},
155+
{
156+
"client": "client",
157+
"eventType": "sdam",
158+
"ignoreExtraEvents": false,
159+
"events": [
160+
{
161+
"serverHeartbeatSucceededEvent": {}
162+
},
163+
{
164+
"serverDescriptionChangedEvent": {}
165+
}
166+
]
142167
}
143168
]
144169
}

test/discovery_and_monitoring/unified/backpressure-network-timeout-fail.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"useMultipleMongoses": false,
5050
"observeEvents": [
5151
"serverHeartbeatSucceededEvent",
52+
"serverDescriptionChangedEvent",
5253
"poolReadyEvent",
5354
"poolClearedEvent"
5455
],
@@ -91,6 +92,17 @@
9192
"count": 1
9293
}
9394
},
95+
{
96+
"name": "waitForEvent",
97+
"object": "testRunner",
98+
"arguments": {
99+
"client": "client",
100+
"event": {
101+
"serverDescriptionChangedEvent": {}
102+
},
103+
"count": 1
104+
}
105+
},
94106
{
95107
"name": "failPoint",
96108
"object": "testRunner",
@@ -141,6 +153,19 @@
141153
"poolReadyEvent": {}
142154
}
143155
]
156+
},
157+
{
158+
"client": "client",
159+
"eventType": "sdam",
160+
"ignoreExtraEvents": false,
161+
"events": [
162+
{
163+
"serverHeartbeatSucceededEvent": {}
164+
},
165+
{
166+
"serverDescriptionChangedEvent": {}
167+
}
168+
]
144169
}
145170
]
146171
}

0 commit comments

Comments
 (0)