Skip to content

Commit 5c79502

Browse files
committed
PYTHON-2560 Retry KMS requests on transient errors
1 parent f45b35a commit 5c79502

File tree

2 files changed

+24
-16
lines changed

2 files changed

+24
-16
lines changed

pymongo/asynchronous/encryption.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@
7272
EncryptedCollectionError,
7373
EncryptionError,
7474
InvalidOperation,
75-
PyMongoError,
7675
ServerSelectionTimeoutError,
7776
)
7877
from pymongo.network_layer import BLOCKING_IO_ERRORS, async_sendall
@@ -176,6 +175,9 @@ async def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
176175
ssl_context=ctx,
177176
)
178177
host, port = parse_host(endpoint, _HTTPS_PORT)
178+
sleep_usec = kms_context.usleep
179+
if sleep_usec:
180+
await asyncio.sleep(float(sleep_usec) / 1e6)
179181
try:
180182
conn = await _configured_socket((host, port), opts)
181183
try:
@@ -201,13 +203,15 @@ async def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
201203
raise socket.timeout("timed out") from None
202204
finally:
203205
conn.close()
204-
except (PyMongoError, MongoCryptError):
205-
raise # Propagate pymongo errors directly.
206-
except asyncio.CancelledError:
207-
raise
208-
except Exception as error:
209-
# Wrap I/O errors in PyMongo exceptions.
210-
_raise_connection_failure((host, port), error)
206+
except MongoCryptError:
207+
raise # Propagate MongoCryptError errors directly.
208+
except Exception as exc:
209+
remaining = _csot.remaining()
210+
if remaining is not None and remaining <= 0:
211+
# Wrap I/O errors in PyMongo exceptions.
212+
_raise_connection_failure((host, port), exc)
213+
# Mark this attempt as failed and defer to libmongocrypt to retry.
214+
kms_context.fail()
211215

212216
async def collection_info(self, database: str, filter: bytes) -> Optional[bytes]:
213217
"""Get the collection info for a namespace.

pymongo/synchronous/encryption.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
EncryptedCollectionError,
6868
EncryptionError,
6969
InvalidOperation,
70-
PyMongoError,
7170
ServerSelectionTimeoutError,
7271
)
7372
from pymongo.network_layer import BLOCKING_IO_ERRORS, sendall
@@ -176,6 +175,9 @@ def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
176175
ssl_context=ctx,
177176
)
178177
host, port = parse_host(endpoint, _HTTPS_PORT)
178+
sleep_usec = kms_context.usleep
179+
if sleep_usec:
180+
asyncio.sleep(float(sleep_usec) / 1e6)
179181
try:
180182
conn = _configured_socket((host, port), opts)
181183
try:
@@ -201,13 +203,15 @@ def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
201203
raise socket.timeout("timed out") from None
202204
finally:
203205
conn.close()
204-
except (PyMongoError, MongoCryptError):
205-
raise # Propagate pymongo errors directly.
206-
except asyncio.CancelledError:
207-
raise
208-
except Exception as error:
209-
# Wrap I/O errors in PyMongo exceptions.
210-
_raise_connection_failure((host, port), error)
206+
except MongoCryptError:
207+
raise # Propagate MongoCryptError errors directly.
208+
except Exception as exc:
209+
remaining = _csot.remaining()
210+
if remaining is not None and remaining <= 0:
211+
# Wrap I/O errors in PyMongo exceptions.
212+
_raise_connection_failure((host, port), exc)
213+
# Mark this attempt as failed and defer to libmongocrypt to retry.
214+
kms_context.fail()
211215

212216
def collection_info(self, database: str, filter: bytes) -> Optional[bytes]:
213217
"""Get the collection info for a namespace.

0 commit comments

Comments
 (0)