Skip to content

Commit

Permalink
Properly populate and invalidate local_cache in cas and cas_multi
Browse files Browse the repository at this point in the history
  • Loading branch information
byroot committed Aug 18, 2021
1 parent 1cb8312 commit 3ed14ed
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 4 deletions.
29 changes: 25 additions & 4 deletions lib/active_support/cache/memcached_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,27 @@ def read_multi(*names)
def cas(name, options = nil)
options = merged_options(options)
key = normalize_key(name, options)
payload = nil

handle_exceptions(return_value_on_error: false) do
success = handle_exceptions(return_value_on_error: false) do
instrument(:cas, name, options) do
@connection.cas(key, expiration(options)) do |raw_value|
entry = deserialize_entry(raw_value)
value = yield entry.value
serialize_entry(Entry.new(value, **options), **options)
payload = serialize_entry(Entry.new(value, **options), **options)
end
end
true
end

success = success != false # can return nil on success

if success
local_cache.write_entry(key, payload) if local_cache
else
local_cache.delete_entry(key) if local_cache
end

success
end

def cas_multi(*names, **options)
Expand All @@ -101,7 +111,7 @@ def cas_multi(*names, **options)

handle_exceptions(return_value_on_error: false) do
instrument(:cas_multi, names, options) do
@connection.cas(keys_to_names.keys, expiration(options)) do |raw_values|
written_payloads = @connection.cas(keys_to_names.keys, expiration(options)) do |raw_values|
values = {}

raw_values.each do |key, raw_value|
Expand All @@ -117,6 +127,17 @@ def cas_multi(*names, **options)

Hash[serialized_values]
end

if local_cache
keys_to_names.each_key do |key|
if written_payloads.key?(key)
local_cache.write_entry(key, written_payloads[key])
else
local_cache.delete_entry(key)
end
end
end

true
end
end
Expand Down
36 changes: 36 additions & 0 deletions test/test_memcached_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ def test_cas
assert_equal 'bar', @cache.read('foo')
end

def test_cas_local_cache
@cache.with_local_cache do
@cache.write('foo', 'plop')
assert(@cache.cas('foo') do |value|
assert_equal 'plop', value
'bar'
end)
assert_equal 'bar', @cache.read('foo')
assert_equal 'bar', @peek.read('foo')
end
end

def test_cas_with_cache_miss
refute @cache.cas('not_exist') { |_value| flunk }
end
Expand All @@ -93,6 +105,17 @@ def test_cas_with_conflict
assert_equal 'baz', @cache.read('foo')
end

def test_cas_local_cache_with_conflict
@cache.with_local_cache do
@cache.write('foo', 'bar')
refute @cache.cas('foo') { |_value|
@peek.write('foo', 'baz')
'biz'
}
assert_equal 'baz', @cache.read('foo')
end
end

def test_cas_multi_with_empty_set
refute @cache.cas_multi { |_hash| flunk }
end
Expand All @@ -107,6 +130,19 @@ def test_cas_multi
assert_equal({ "foo" => "baz", "fud" => "buz" }, @cache.read_multi('foo', 'fud'))
end

def test_cas_multi_with_local_cache
@cache.with_local_cache do
@cache.write('foo', 'bar')
@cache.write('fud', 'biz')
assert_equal true, (@cache.cas_multi('foo', 'fud') do |hash|
assert_equal({ "foo" => "bar", "fud" => "biz" }, hash)
@peek.write('fud', 'blam')
{ "foo" => "baz", "fud" => "buz" }
end)
assert_equal({ "foo" => "baz", "fud" => "blam" }, @cache.read_multi('foo', 'fud'))
end
end

def test_cas_multi_with_altered_key
@cache.write('foo', 'baz')
assert @cache.cas_multi('foo') { |_hash| { 'fu' => 'baz' } }
Expand Down

0 comments on commit 3ed14ed

Please sign in to comment.