Skip to content

RUBY-3524 Add option to configure DEK cache lifetime - #3098

Merged
comandeo-mongo merged 1 commit into
mongodb:masterfrom
comandeo-mongo:3524-dek-cache-lifetime
Jul 30, 2026
Merged

RUBY-3524 Add option to configure DEK cache lifetime#3098
comandeo-mongo merged 1 commit into
mongodb:masterfrom
comandeo-mongo:3524-dek-cache-lifetime

Conversation

@comandeo-mongo

@comandeo-mongo comandeo-mongo commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

RUBY-3524

Adds a key_expiration_ms option that controls how long libmongocrypt caches
decrypted data encryption keys. Increasing it reduces the rate of KMS requests
under heavy load, which is the problem DRIVERS-2781
was filed for.

The option is accepted in two places, per the
client-side-encryption spec
(AutoEncryptionOpts and ClientEncryptionOpts, both Optional<Uint64>,
default 60000, 0 meaning "never expire"):

Mongo::Client.new(uri, auto_encryption_options: { ..., key_expiration_ms: 300_000 })
Mongo::ClientEncryption.new(key_vault_client, ..., key_expiration_ms: 300_000)

When the option is not given, no setopt call is made and libmongocrypt's
60000 ms default applies. This matters because 0 is a meaningful value, so
"unset" cannot be collapsed into 0.

mongocrypt_setopt_key_expiration has been exported since libmongocrypt
1.12.0 and MIN_LIBMONGOCRYPT_VERSION is already 1.20.0, so no version bump
is needed.

Changes

Option plumbing:

  • lib/mongo/crypt/binding.rb — bind mongocrypt_setopt_key_expiration and add a setopt_key_expiration wrapper that raises Mongo::Error::CryptError on failure
  • lib/mongo/crypt/handle.rb — accept :key_expiration_ms, validate it, and set it before mongocrypt_init
  • lib/mongo/crypt/auto_encrypter.rb — forward the option from auto_encryption_options
  • lib/mongo/crypt/explicit_encrypter.rb, lib/mongo/client_encryption.rb — forward the option from ClientEncryption

Documentation:

  • lib/mongo/client.rb — document :key_expiration_ms under :auto_encryption_options

Tests:

  • spec/spec_tests/data/client_side_encryption/unified/keyCache.yml — spec fixture, copied unmodified from specifications
  • spec/runners/unified/test.rb — read keyExpirationMS from clientEncryptionOpts
  • spec/mongo/crypt/handle_spec.rb — validation and pass-through cases the unified format cannot express

A non-Integer or negative value raises ArgumentError. This is stricter
than the driver's timeout_ms (which only rejects negatives) but matches the
existing validation style in Handle and avoids a confusing FFI error when
marshalling to uint64.

Adds a key_expiration_ms option to both auto_encryption_options and
ClientEncryption, wired to libmongocrypt's mongocrypt_setopt_key_expiration.
A value of 0 means the data encryption key cache never expires; when the
option is not given, libmongocrypt's 60000 ms default applies.

libmongocrypt has exported this setopt since 1.12.0 and the driver already
requires 1.20.0, so no version bump is needed.
@comandeo-mongo comandeo-mongo added the feature A PR for a new feature label Jul 30, 2026
@comandeo-mongo
comandeo-mongo marked this pull request as ready for review July 30, 2026 10:44
@comandeo-mongo
comandeo-mongo requested a review from a team as a code owner July 30, 2026 10:44
@comandeo-mongo
comandeo-mongo requested review from Copilot and jamis July 30, 2026 10:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for configuring libmongocrypt’s decrypted data encryption key (DEK) cache lifetime via a new :key_expiration_ms option, enabling applications using CSFLE to reduce KMS traffic under heavy load.

Changes:

  • Adds an FFI binding and Mongo::Crypt::Handle plumbing to set mongocrypt_setopt_key_expiration before mongocrypt_init.
  • Plumbs :key_expiration_ms through auto-encryption and explicit ClientEncryption APIs, with associated documentation updates.
  • Adds coverage via a new unified spec fixture and targeted RSpec validation/pass-through tests.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
spec/spec_tests/data/client_side_encryption/unified/keyCache.yml Adds unified test verifying DEK cache expiration behavior.
spec/runners/unified/test.rb Plumbs keyExpirationMS from unified clientEncryptionOpts into driver options.
spec/mongo/crypt/handle_spec.rb Adds RSpec coverage for :key_expiration_ms validation and nil/0 behavior.
lib/mongo/crypt/handle.rb Validates and applies :key_expiration_ms via binding prior to mongocrypt_init.
lib/mongo/crypt/explicit_encrypter.rb Accepts and forwards key_expiration_ms to Mongo::Crypt::Handle.
lib/mongo/crypt/binding.rb Binds mongocrypt_setopt_key_expiration and exposes a checked wrapper.
lib/mongo/crypt/auto_encrypter.rb Forwards :key_expiration_ms from auto-encryption options into the handle.
lib/mongo/client.rb Documents :key_expiration_ms under :auto_encryption_options.
lib/mongo/client_encryption.rb Documents and forwards :key_expiration_ms through ClientEncryption to explicit encrypter.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +45 to +48
# @option options [ Integer ] :key_expiration_ms The lifetime of the data
# encryption key cache, in milliseconds. Must be a non-negative integer.
# An explicit value of 0 means the cache never expires. The default is
# 60000.
Comment thread lib/mongo/crypt/handle.rb
Comment on lines +210 to +216
def set_key_expiration
unless @key_expiration_ms.is_a?(Integer) && !@key_expiration_ms.negative?
raise ArgumentError.new(
"#{@key_expiration_ms} is an invalid key_expiration_ms value; " \
'must be a non-negative Integer or nil'
)
end
@comandeo-mongo
comandeo-mongo merged commit edab445 into mongodb:master Jul 30, 2026
220 checks passed
@comandeo-mongo
comandeo-mongo deleted the 3524-dek-cache-lifetime branch July 30, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature A PR for a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants