Memoize key_provider
from key
or deterministic key_provider
if any
#51324
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation / Background
We're in the process of bringing one of our apps up to date with
main
, and in the process of doing so, we realised our tests were taking about 5 times longer to run. We traced the slowdown back to #51019.The memoization of
Scheme#key_provider
was removed completely in that PR because it prevented overriding thekey_provider
viawith_encryption_context
. For encrypted attributes where we either provide a key or declare them as deterministic, we have to derive a key to instantiate the provider every time we load them. This might happen hundreds of times per test, and ultimately means we calland
hundreds of times. This adds significant overhead per test.
In reality, what's overridden by
with_encryption_context
is the value used as default provider, that is,ActiveRecord::Encryption.key_provider
. This is only used inScheme#key_provider
if the scheme doesn't already have either akey_provider
passed directly, or akey
, or isdeterministic
, because it's called viadefault_key_provider
here:rails/activerecord/lib/active_record/encryption/scheme.rb
Lines 52 to 54 in 3efae44
rails/activerecord/lib/active_record/encryption/scheme.rb
Lines 91 to 93 in 3efae44
However,
build_key_provider
takes precedence, and it's very expensive to do:rails/activerecord/lib/active_record/encryption/scheme.rb
Lines 83 to 89 in 3efae44
Neither
@key
nor@deterministic
can be overridden, so this PR memoizes them if we have to build them.Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
cc @jhawthorn @kstevens715