From d5c7f7cc06999a56cc8893f607f0c0cd7736bf4f Mon Sep 17 00:00:00 2001 From: Mark Oleson Date: Tue, 5 Dec 2023 13:49:29 -0500 Subject: [PATCH] fix LocalCache#read_multi_entries not namespacing keys before looking them up in the cache --- activesupport/lib/active_support/cache.rb | 2 +- .../active_support/cache/strategy/local_cache.rb | 15 +++++++++------ .../test/cache/behaviors/local_cache_behavior.rb | 14 +++++++++++++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 94435b7355117..a21c3b1c098ba 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -826,7 +826,7 @@ def serialize_entry(entry, **options) end end - def deserialize_entry(payload) + def deserialize_entry(payload, **) payload.nil? ? nil : @coder.load(payload) rescue DeserializationError nil diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb index 9cd3a8db4f63d..ea8b9548abd97 100644 --- a/activesupport/lib/active_support/cache/strategy/local_cache.rb +++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb @@ -131,17 +131,20 @@ def read_serialized_entry(key, raw: false, **options) end end - def read_multi_entries(keys, **options) + def read_multi_entries(names, **options) return super unless local_cache - local_entries = local_cache.read_multi_entries(keys) + keys_to_names = names.index_by { |name| normalize_key(name, options) } + + local_entries = local_cache.read_multi_entries(keys_to_names.keys) + local_entries.transform_keys! { |key| keys_to_names[key] } local_entries.transform_values! do |payload| - deserialize_entry(payload)&.value + deserialize_entry(payload, **options)&.value end - missed_keys = keys - local_entries.keys + missed_names = names - local_entries.keys - if missed_keys.any? - local_entries.merge!(super(missed_keys, **options)) + if missed_names.any? + local_entries.merge!(super(missed_names, **options)) else local_entries end diff --git a/activesupport/test/cache/behaviors/local_cache_behavior.rb b/activesupport/test/cache/behaviors/local_cache_behavior.rb index 05a41b1d456e8..b20cce4a898fc 100644 --- a/activesupport/test/cache/behaviors/local_cache_behavior.rb +++ b/activesupport/test/cache/behaviors/local_cache_behavior.rb @@ -190,6 +190,7 @@ def test_local_cache_of_increment @cache.with_local_cache do @cache.write(key, 1, raw: true) @peek.write(key, 2, raw: true) + @cache.increment(key) expected = @peek.read(key, raw: true) @@ -205,6 +206,7 @@ def test_local_cache_of_decrement @peek.write(key, 3, raw: true) @cache.decrement(key) + expected = @peek.read(key, raw: true) assert_equal 2, Integer(expected) assert_equal expected, @cache.read(key, raw: true) @@ -230,7 +232,7 @@ def test_local_cache_of_read_multi other_value = SecureRandom.alphanumeric @cache.with_local_cache do @cache.write(key, value, raw: true) - @cache.write(other_key, other_value, raw: true) + @peek.write(other_key, other_value, raw: true) values = @cache.read_multi(key, other_key, raw: true) assert_equal value, @cache.read(key, raw: true) assert_equal other_value, @cache.read(other_key, raw: true) @@ -239,6 +241,16 @@ def test_local_cache_of_read_multi end end + def test_local_cache_of_read_multi_prioritizes_local_entries + key = "key#{rand}" + @cache.with_local_cache do + @cache.write(key, "foo") + @cache.send(:bypass_local_cache) { @cache.write(key, "bar") } + + assert_equal({ key => "foo" }, @cache.read_multi(key)) + end + end + def test_initial_object_mutation_after_write key = SecureRandom.uuid @cache.with_local_cache do