Uploaded image for project: 'Libmongocrypt'
  1. Libmongocrypt
  2. MONGOCRYPT-763

Support retrying a KMS in-place

    • Type: Icon: Improvement Improvement
    • Resolution: Unresolved
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Needed

      Summary

      Support retrying a KMS in-place.

      This is expected to simplify driver implementations that fan out KMS requests in parallel (so far, only Node) and reduce time between retries.

      Background & Motivation
      Quoting integrating.md:

      Note, the driver MAY fan out KMS requests in parallel. More KMS requests may be added when processing responses to retry.

      This poses an implementation difficulty for drivers that want to run KMS requests in parallel. In Node, a proposed implementation (in pseudo-code) batches requests:

      while (true) {
        let requests = []
        for (let request = mongocrypt_ctx_kms_next(); request != null; request = mongocrypt_ctx_kms_next()) {
          requests.push(request);
        }
        if (request.length === 0) break;
        execute_requests(requests); // Blocks until all requests complete.
      }
      

      As a result, retries are unable to start until the slowest request in the batch returns. Drivers are expected to sleep for mongocrypt_kms_ctx_usleep between retries, but this implementation may wait longer.

      mongocrypt_ctx_next_kms_ctx may return NULL (to signal no more immediate requests), then later return non-NULL if retries are needed. In test code this looks like:

      mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx);
      ASSERT_OK(kms_ctx, ctx);
      // Expect no more immediate KMS requests.
      ASSERT(!mongocrypt_ctx_next_kms_ctx(ctx));
      // Feed a retryable HTTP error.
      ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kms_ctx);
      // Expect KMS request is returned again for a retry.
      kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx);
      ASSERT_OK(kms_ctx, ctx);
      // Feed a successful response.
      ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-aws/encrypt-response.txt")), kms_ctx);
      ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx);
      

      This ticket proposes adding API to permit an in-place retry, to avoid the need to iterate with mongocrypt_ctx_next_kms_ctx for retry attempts:

      mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx);
      ASSERT_OK(kms_ctx, ctx);
      // Expect no more immediate KMS requests.
      ASSERT(!mongocrypt_ctx_next_kms_ctx(ctx));
      // Feed a retryable HTTP error.
      ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kms_ctx);
      // Expect KMS request can be retried in-place.
      ASSERT(mongocrypt_kms_ctx_reset_and_retry(kms_ctx)); // Proposed API.
      // Feed a successful response.
      ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-aws/encrypt-response.txt")), kms_ctx);
      ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx);
      

      Caveats
      This change may further complicate the protocol, resulting in two ways to support retry.

            Assignee:
            Unassigned Unassigned
            Reporter:
            kevin.albertson@mongodb.com Kevin Albertson
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: