Skip to content

Commit 30f6b28

Browse files
committed
Merge pull request rails#55000 from Shopify/rescue_dalli_timeout_in_read_multi_entries
Rescue connection related errors in MemCacheStore#read_multi_entries
1 parent 4053377 commit 30f6b28

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

activesupport/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
* Fix `ActiveSupport::Cache::MemCacheStore#read_multi` to handle network errors.
2+
3+
This method specifically wasn't handling network errors like other codepaths.
4+
5+
*Alessandro Dal Grande*
6+
17
* Fix Active Support Cache `fetch_multi` when local store is active.
28

39
`fetch_multi` now properly yield to the provided block for missing entries

activesupport/lib/active_support/cache/mem_cache_store.rb

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -212,26 +212,24 @@ def write_serialized_entry(key, payload, **options)
212212
def read_multi_entries(names, **options)
213213
keys_to_names = names.index_by { |name| normalize_key(name, options) }
214214

215-
raw_values = begin
216-
@data.with { |c| c.get_multi(keys_to_names.keys) }
217-
rescue Dalli::UnmarshalError
218-
{}
219-
end
215+
rescue_error_with({}) do
216+
raw_values = @data.with { |c| c.get_multi(keys_to_names.keys) }
220217

221-
values = {}
218+
values = {}
222219

223-
raw_values.each do |key, value|
224-
entry = deserialize_entry(value, raw: options[:raw])
220+
raw_values.each do |key, value|
221+
entry = deserialize_entry(value, raw: options[:raw])
225222

226-
unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
227-
begin
228-
values[keys_to_names[key]] = entry.value
229-
rescue DeserializationError
223+
unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
224+
begin
225+
values[keys_to_names[key]] = entry.value
226+
rescue DeserializationError
227+
end
230228
end
231229
end
232-
end
233230

234-
values
231+
values
232+
end
235233
end
236234

237235
# Delete an entry from the cache.

activesupport/test/cache/stores/mem_cache_store_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,30 @@ def test_can_read_multi_entries_raw_values_from_dalli_store
371371
assert_equal({}, @cache.send(:read_multi_entries, [key]))
372372
end
373373

374+
def test_falls_back_to_default_value_when_client_raises_dalli_error
375+
cache = lookup_store
376+
client = cache.instance_variable_get(:@data)
377+
client.stub(:get_multi, lambda { |*_args| raise Dalli::DalliError.new("test error") }) do
378+
assert_equal({}, cache.read_multi("key1", "key2"))
379+
end
380+
end
381+
382+
def test_falls_back_to_default_value_when_client_raises_connection_pool_timeout_error
383+
cache = lookup_store
384+
client = cache.instance_variable_get(:@data)
385+
client.stub(:get_multi, lambda { |*_args| raise ConnectionPool::TimeoutError.new("test error") }) do
386+
assert_equal({}, cache.read_multi("key1", "key2"))
387+
end
388+
end
389+
390+
def test_falls_back_to_default_value_when_client_raises_connection_pool_error
391+
cache = lookup_store
392+
client = cache.instance_variable_get(:@data)
393+
client.stub(:get_multi, lambda { |*_args| raise ConnectionPool::Error.new("test error") }) do
394+
assert_equal({}, cache.read_multi("key1", "key2"))
395+
end
396+
end
397+
374398
def test_pool_options_work
375399
cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, pool: { size: 2, timeout: 1 })
376400
pool = cache.instance_variable_get(:@data) # loads 'connection_pool' gem

0 commit comments

Comments
 (0)