Skip to content

Commit 9262d91

Browse files
authored
PYTHON-4992 Support retrying KMS requests (#920)
1 parent 54a839b commit 9262d91

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

bindings/python/pymongocrypt/binding.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,17 @@ def _parse_version(version):
312312
*/
313313
bool mongocrypt_setopt_log_handler(mongocrypt_t *crypt, mongocrypt_log_fn_t log_fn, void *log_ctx);
314314
315+
/**
316+
* Enable or disable KMS retry behavior.
317+
*
318+
* @param[in] crypt The @ref mongocrypt_t object.
319+
* @param[in] enable A boolean indicating whether to retry operations.
320+
* @pre @ref mongocrypt_init has not been called on @p crypt.
321+
* @returns A boolean indicating success. If false, an error status is set.
322+
* Retrieve it with @ref mongocrypt_ctx_status
323+
*/
324+
bool mongocrypt_setopt_retry_kms(mongocrypt_t *crypt, bool enable);
325+
315326
/**
316327
* Configure an AWS KMS provider on the @ref mongocrypt_t object.
317328
*
@@ -1042,6 +1053,8 @@ def _parse_version(version):
10421053
* If KMS handles are being handled synchronously, the driver can reuse the same
10431054
* TLS socket to send HTTP requests and receive responses.
10441055
*
1056+
* The returned KMS handle does not outlive `ctx`.
1057+
*
10451058
* @param[in] ctx A @ref mongocrypt_ctx_t.
10461059
* @returns a new @ref mongocrypt_kms_ctx_t or NULL.
10471060
*/
@@ -1086,6 +1099,14 @@ def _parse_version(version):
10861099
*/
10871100
uint32_t mongocrypt_kms_ctx_bytes_needed(mongocrypt_kms_ctx_t *kms);
10881101
1102+
/**
1103+
* Indicates how long to sleep before sending this request.
1104+
*
1105+
* @param[in] kms The @ref mongocrypt_kms_ctx_t.
1106+
* @returns How long to sleep in microseconds.
1107+
*/
1108+
int64_t mongocrypt_kms_ctx_usleep(mongocrypt_kms_ctx_t *kms);
1109+
10891110
/**
10901111
* Feed bytes from the HTTP response.
10911112
*
@@ -1100,6 +1121,14 @@ def _parse_version(version):
11001121
*/
11011122
bool mongocrypt_kms_ctx_feed(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes);
11021123
1124+
/**
1125+
* Indicate a network-level failure.
1126+
*
1127+
* @param[in] kms The @ref mongocrypt_kms_ctx_t.
1128+
* @return A boolean indicating whether the failed request may be retried.
1129+
*/
1130+
bool mongocrypt_kms_ctx_fail(mongocrypt_kms_ctx_t *kms);
1131+
11031132
/**
11041133
* Get the status associated with a @ref mongocrypt_kms_ctx_t object.
11051134
*
@@ -1413,7 +1442,7 @@ def _parse_version(version):
14131442
* {
14141443
* "min": Optional<BSON value>,
14151444
* "max": Optional<BSON value>,
1416-
* "sparsity": Int64,
1445+
* "sparsity": Optional<Int64>,
14171446
* "precision": Optional<Int32>,
14181447
* "trimFactor": Optional<Int32>
14191448
* }
@@ -1426,6 +1455,15 @@ def _parse_version(version):
14261455
*/
14271456
bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *opts);
14281457
1458+
/**
1459+
* Set the expiration time for the data encryption key cache. Defaults to 60 seconds if not set.
1460+
*
1461+
* @param[in] ctx The @ref mongocrypt_ctx_t object.
1462+
* @param[in] cache_expiration_ms The cache expiration time in milliseconds. If zero, the cache
1463+
* never expires.
1464+
*/
1465+
bool mongocrypt_setopt_key_expiration(mongocrypt_t *crypt, uint64_t cache_expiration_ms);
1466+
14291467
/// String constants for setopt_query_type
14301468
// DEPRECATED: Support "rangePreview" has been removed in favor of "range".
14311469
"""

bindings/python/pymongocrypt/mongocrypt.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ def __init(self):
149149
if any([on_demand_aws, on_demand_gcp, on_demand_azure]):
150150
lib.mongocrypt_setopt_use_need_kms_credentials_state(self.__crypt)
151151

152+
# Enable KMS retry when available, libmongocrypt >= 1.12.0,
153+
try:
154+
if not lib.mongocrypt_setopt_retry_kms(self.__crypt, True):
155+
self.__raise_from_status()
156+
except AttributeError:
157+
# libmongocrypt < 1.12
158+
pass
159+
152160
if not lib.mongocrypt_init(self.__crypt):
153161
self.__raise_from_status()
154162

@@ -670,6 +678,30 @@ def feed(self, data):
670678
if not lib.mongocrypt_kms_ctx_feed(self.__ctx, binary.bin):
671679
self.__raise_from_status()
672680

681+
@property
682+
def usleep(self):
683+
"""Indicates how long to sleep in microseconds before sending this request.
684+
685+
.. versionadded:: 1.12
686+
"""
687+
try:
688+
return lib.mongocrypt_kms_ctx_usleep(self.__ctx)
689+
except AttributeError:
690+
# libmongocrypt < 1.12
691+
return 0
692+
693+
def fail(self):
694+
"""Indicate a network-level failure.
695+
696+
.. versionadded:: 1.12
697+
"""
698+
try:
699+
if not lib.mongocrypt_kms_ctx_fail(self.__ctx):
700+
self.__raise_from_status()
701+
except AttributeError:
702+
# libmongocrypt < 1.12
703+
pass
704+
673705
def __raise_from_status(self):
674706
status = lib.mongocrypt_status_new()
675707
try:

0 commit comments

Comments
 (0)