Skip to content

Commit 3ed14ed

Browse files
committed
Properly populate and invalidate local_cache in cas and cas_multi
1 parent 1cb8312 commit 3ed14ed

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

lib/active_support/cache/memcached_store.rb

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,27 @@ def read_multi(*names)
8080
def cas(name, options = nil)
8181
options = merged_options(options)
8282
key = normalize_key(name, options)
83+
payload = nil
8384

84-
handle_exceptions(return_value_on_error: false) do
85+
success = handle_exceptions(return_value_on_error: false) do
8586
instrument(:cas, name, options) do
8687
@connection.cas(key, expiration(options)) do |raw_value|
8788
entry = deserialize_entry(raw_value)
8889
value = yield entry.value
89-
serialize_entry(Entry.new(value, **options), **options)
90+
payload = serialize_entry(Entry.new(value, **options), **options)
9091
end
9192
end
92-
true
9393
end
94+
95+
success = success != false # can return nil on success
96+
97+
if success
98+
local_cache.write_entry(key, payload) if local_cache
99+
else
100+
local_cache.delete_entry(key) if local_cache
101+
end
102+
103+
success
94104
end
95105

96106
def cas_multi(*names, **options)
@@ -101,7 +111,7 @@ def cas_multi(*names, **options)
101111

102112
handle_exceptions(return_value_on_error: false) do
103113
instrument(:cas_multi, names, options) do
104-
@connection.cas(keys_to_names.keys, expiration(options)) do |raw_values|
114+
written_payloads = @connection.cas(keys_to_names.keys, expiration(options)) do |raw_values|
105115
values = {}
106116

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

118128
Hash[serialized_values]
119129
end
130+
131+
if local_cache
132+
keys_to_names.each_key do |key|
133+
if written_payloads.key?(key)
134+
local_cache.write_entry(key, written_payloads[key])
135+
else
136+
local_cache.delete_entry(key)
137+
end
138+
end
139+
end
140+
120141
true
121142
end
122143
end

test/test_memcached_store.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ def test_cas
8080
assert_equal 'bar', @cache.read('foo')
8181
end
8282

83+
def test_cas_local_cache
84+
@cache.with_local_cache do
85+
@cache.write('foo', 'plop')
86+
assert(@cache.cas('foo') do |value|
87+
assert_equal 'plop', value
88+
'bar'
89+
end)
90+
assert_equal 'bar', @cache.read('foo')
91+
assert_equal 'bar', @peek.read('foo')
92+
end
93+
end
94+
8395
def test_cas_with_cache_miss
8496
refute @cache.cas('not_exist') { |_value| flunk }
8597
end
@@ -93,6 +105,17 @@ def test_cas_with_conflict
93105
assert_equal 'baz', @cache.read('foo')
94106
end
95107

108+
def test_cas_local_cache_with_conflict
109+
@cache.with_local_cache do
110+
@cache.write('foo', 'bar')
111+
refute @cache.cas('foo') { |_value|
112+
@peek.write('foo', 'baz')
113+
'biz'
114+
}
115+
assert_equal 'baz', @cache.read('foo')
116+
end
117+
end
118+
96119
def test_cas_multi_with_empty_set
97120
refute @cache.cas_multi { |_hash| flunk }
98121
end
@@ -107,6 +130,19 @@ def test_cas_multi
107130
assert_equal({ "foo" => "baz", "fud" => "buz" }, @cache.read_multi('foo', 'fud'))
108131
end
109132

133+
def test_cas_multi_with_local_cache
134+
@cache.with_local_cache do
135+
@cache.write('foo', 'bar')
136+
@cache.write('fud', 'biz')
137+
assert_equal true, (@cache.cas_multi('foo', 'fud') do |hash|
138+
assert_equal({ "foo" => "bar", "fud" => "biz" }, hash)
139+
@peek.write('fud', 'blam')
140+
{ "foo" => "baz", "fud" => "buz" }
141+
end)
142+
assert_equal({ "foo" => "baz", "fud" => "blam" }, @cache.read_multi('foo', 'fud'))
143+
end
144+
end
145+
110146
def test_cas_multi_with_altered_key
111147
@cache.write('foo', 'baz')
112148
assert @cache.cas_multi('foo') { |_hash| { 'fu' => 'baz' } }

0 commit comments

Comments
 (0)