From 0f75c64e6f46d06e9a41880b01fefc3a8cc47948 Mon Sep 17 00:00:00 2001 From: Sylvain Lemiere Date: Tue, 28 Mar 2017 16:59:44 -0400 Subject: [PATCH] Raise on id mismatch from the cache --- lib/identity_cache.rb | 5 +++++ lib/identity_cache/query_api.rb | 7 ++++++- test/fetch_test.rb | 9 +++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/identity_cache.rb b/lib/identity_cache.rb index 7b05bff7..3db3429d 100644 --- a/lib/identity_cache.rb +++ b/lib/identity_cache.rb @@ -55,6 +55,11 @@ class << self mattr_accessor :fetch_read_only_records self.fetch_read_only_records = true + # Raise an exception if the record returned from the cache don't match the id + # the user expected + mattr_accessor :raise_on_id_mismatch + self.raise_on_id_mismatch = false + mattr_accessor :lazy_load_associated_classes self.lazy_load_associated_classes = Gem::Version.new(IdentityCache::VERSION) >= Gem::Version.new("0.6") diff --git a/lib/identity_cache/query_api.rb b/lib/identity_cache/query_api.rb index 4331819e..0955a78b 100644 --- a/lib/identity_cache/query_api.rb +++ b/lib/identity_cache/query_api.rb @@ -1,4 +1,7 @@ module IdentityCache + class CorruptedCache < StandardError + end + module QueryAPI extend ActiveSupport::Concern @@ -27,7 +30,9 @@ def fetch_by_id(id, options={}) coder = IdentityCache.fetch(rails_cache_key(id)){ coder_from_record(object = resolve_cache_miss(id)) } object ||= record_from_coder(coder) if object && object.id.to_s != id.to_s - IdentityCache.logger.error "[IDC id mismatch] fetch_by_id_requested=#{id} fetch_by_id_got=#{object.id} for #{object.inspect[(0..100)]}" + message = "[IDC id mismatch] fetch_by_id_requested=#{id} fetch_by_id_got=#{object.id} for #{object.inspect[(0..100)]}" + IdentityCache.logger.error message + raise CorruptedCache.new(message) if IdentityCache.raise_on_id_mismatch end object end diff --git a/test/fetch_test.rb b/test/fetch_test.rb index f0d77296..95da569c 100644 --- a/test/fetch_test.rb +++ b/test/fetch_test.rb @@ -20,6 +20,15 @@ def test_fetch_with_garbage_input assert_nil Item.fetch_by_id('garbage') end + def test_fetch_with_corrupted_cache + attributes = @record.attributes_before_type_cast + attributes["id"] += 1 + IdentityCache.cache.expects(:fetch).with(@blob_key).returns(class: @record.class.name, attributes: attributes) + + IdentityCache.raise_on_id_mismatch = true + assert_raises(IdentityCache::CorruptedCache) { Item.fetch(1) } + end + def test_fetch_cache_hit IdentityCache.cache.expects(:fetch).with(@blob_key).returns(@cached_value)