Skip to content

Commit 9e5dcb2

Browse files
committed
PYTHON-5672 Fix SDAM error handling when pool checkout raises in __aenter__
When _PoolCheckout.__aenter__() raises (e.g. connect() fails), Python does not call _ClientCheckout.__aexit__(), so handle() was never invoked and the topology never learned about the failure. This caused test_5_check_out_fails_ connection_error to fail (missing PoolClearedEvent) and broke failover tests. Fix: wrap both the pool checkout call and the post-checkout setup in try/except BaseException blocks inside _ClientCheckout.__aenter__(), calling handle() and (for post-checkout failures) checking the connection back in before re-raising.
1 parent 9b09a4e commit 9e5dcb2

2 files changed

Lines changed: 66 additions & 38 deletions

File tree

pymongo/asynchronous/mongo_client.py

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,26 +2717,40 @@ async def __aenter__(self) -> AsyncConnection:
27172717
self.contribute_socket(session._pinned_connection)
27182718
return session._pinned_connection
27192719
pool_checkout = _PoolCheckout(server.pool, self)
2720-
conn = await pool_checkout.__aenter__()
2720+
try:
2721+
conn = await pool_checkout.__aenter__()
2722+
except BaseException as exc:
2723+
# __aenter__ raised — pool already cleaned up internally.
2724+
# Run SDAM error handling so the topology learns about the failure.
2725+
await self.handle(type(exc), exc)
2726+
raise
27212727
self._pool_checkout = pool_checkout
2722-
# Pin this session to the selected server or connection.
2723-
if (
2724-
in_txn
2725-
and session
2726-
and server.description.server_type
2727-
in (
2728-
SERVER_TYPE.Mongos,
2729-
SERVER_TYPE.LoadBalancer,
2730-
)
2731-
):
2732-
session._pin(server, conn)
2733-
self.contribute_socket(conn)
2734-
if (
2735-
self.client._encrypter
2736-
and not self.client._encrypter._bypass_auto_encryption
2737-
and conn.max_wire_version < 8
2738-
):
2739-
raise ConfigurationError("Auto-encryption requires a minimum MongoDB version of 4.2")
2728+
try:
2729+
# Pin this session to the selected server or connection.
2730+
if (
2731+
in_txn
2732+
and session
2733+
and server.description.server_type
2734+
in (
2735+
SERVER_TYPE.Mongos,
2736+
SERVER_TYPE.LoadBalancer,
2737+
)
2738+
):
2739+
session._pin(server, conn)
2740+
self.contribute_socket(conn)
2741+
if (
2742+
self.client._encrypter
2743+
and not self.client._encrypter._bypass_auto_encryption
2744+
and conn.max_wire_version < 8
2745+
):
2746+
raise ConfigurationError(
2747+
"Auto-encryption requires a minimum MongoDB version of 4.2"
2748+
)
2749+
except BaseException as exc:
2750+
await self.handle(type(exc), exc)
2751+
await pool_checkout.__aexit__(type(exc), exc, None)
2752+
self._pool_checkout = None
2753+
raise
27402754
return conn
27412755

27422756
async def __aexit__(

pymongo/synchronous/mongo_client.py

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,26 +2706,40 @@ def __enter__(self) -> Connection:
27062706
self.contribute_socket(session._pinned_connection)
27072707
return session._pinned_connection
27082708
pool_checkout = _PoolCheckout(server.pool, self)
2709-
conn = pool_checkout.__enter__()
2709+
try:
2710+
conn = pool_checkout.__enter__()
2711+
except BaseException as exc:
2712+
# __aenter__ raised — pool already cleaned up internally.
2713+
# Run SDAM error handling so the topology learns about the failure.
2714+
self.handle(type(exc), exc)
2715+
raise
27102716
self._pool_checkout = pool_checkout
2711-
# Pin this session to the selected server or connection.
2712-
if (
2713-
in_txn
2714-
and session
2715-
and server.description.server_type
2716-
in (
2717-
SERVER_TYPE.Mongos,
2718-
SERVER_TYPE.LoadBalancer,
2719-
)
2720-
):
2721-
session._pin(server, conn)
2722-
self.contribute_socket(conn)
2723-
if (
2724-
self.client._encrypter
2725-
and not self.client._encrypter._bypass_auto_encryption
2726-
and conn.max_wire_version < 8
2727-
):
2728-
raise ConfigurationError("Auto-encryption requires a minimum MongoDB version of 4.2")
2717+
try:
2718+
# Pin this session to the selected server or connection.
2719+
if (
2720+
in_txn
2721+
and session
2722+
and server.description.server_type
2723+
in (
2724+
SERVER_TYPE.Mongos,
2725+
SERVER_TYPE.LoadBalancer,
2726+
)
2727+
):
2728+
session._pin(server, conn)
2729+
self.contribute_socket(conn)
2730+
if (
2731+
self.client._encrypter
2732+
and not self.client._encrypter._bypass_auto_encryption
2733+
and conn.max_wire_version < 8
2734+
):
2735+
raise ConfigurationError(
2736+
"Auto-encryption requires a minimum MongoDB version of 4.2"
2737+
)
2738+
except BaseException as exc:
2739+
self.handle(type(exc), exc)
2740+
pool_checkout.__exit__(type(exc), exc, None)
2741+
self._pool_checkout = None
2742+
raise
27292743
return conn
27302744

27312745
def __exit__(

0 commit comments

Comments
 (0)