Skip to content

Commit

Permalink
Add expire methods by key values
Browse files Browse the repository at this point in the history
  • Loading branch information
Hector Mendoza Jacobo committed Jun 10, 2021
1 parent b7564e7 commit 94bb7ce
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/identity_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class DerivedModelError < StandardError; end

class LockWaitTimeout < StandardError; end

class MissingKeyName < StandardError ; end

mattr_accessor :cache_namespace
self.cache_namespace = "IDC:#{CACHE_VERSION}:"

Expand Down
22 changes: 22 additions & 0 deletions lib/identity_cache/cached/attribute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ def expire(record)
end
end

def expire_by_key_value(key_values)
missing_keys = missing_keys(key_values)
unless missing_keys.empty?
raise MissingKeyName,
"#{model.name} attribute #{alias_name} expire_by_key_value - "\
"required fields: #{key_fields.join(", ")}. "\
"missing: #{missing_keys.join(", ")}"
end

key = cache_key_by_values(key_values)
IdentityCache.cache.delete(key)
end

def cache_key(index_key)
values_hash = IdentityCache.memcache_hash(unhashed_values_cache_key_string(index_key))
"#{model.rails_cache_key_namespace}#{cache_key_prefix}#{values_hash}"
Expand Down Expand Up @@ -100,6 +113,11 @@ def new_cache_key(record)
cache_key_from_key_values(new_key_values)
end

def cache_key_by_values(key_values)
new_key_values = key_fields.map { |field| key_values[field] }
cache_key_from_key_values(new_key_values)
end

def old_cache_key(record)
old_key_values = key_fields.map do |field|
field_string = field.to_s
Expand All @@ -118,6 +136,10 @@ def old_cache_key(record)
def fetch_method_suffix
"#{alias_name}_by_#{key_fields.join("_and_")}"
end

def missing_keys(key_values)
key_fields - key_values.keys
end
end
end
end
71 changes: 71 additions & 0 deletions test/expire_by_key_values_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# frozen_string_literal: true
require "test_helper"

class ExpireByKeyValuesTest < IdentityCache::TestCase
NAMESPACE = IdentityCache::CacheKeyGeneration::DEFAULT_NAMESPACE

def setup
super
AssociatedRecord.cache_attribute(:name)
AssociatedRecord.cache_attribute(:name, by: :item_id)
AssociatedRecord.cache_attribute(:name, by: [:id, :item_id])

@parent = Item.create!(title: "bob")
@record = @parent.associated_records.create!(name: "foo")
@name_attribute_key = "#{NAMESPACE}attr:AssociatedRecord:name:id:#{cache_hash(@record.id.to_s.inspect)}"
IdentityCache.cache.clear
end

def test_expire_by_key_values
assert_queries(3) do
assert_equal("foo", AssociatedRecord.fetch_name_by_id(1))
assert_equal("foo", AssociatedRecord.fetch_name_by_item_id(1))
assert_equal("foo", AssociatedRecord.fetch_name_by_id_and_item_id(1, 1))
end

assert_queries(0) do
assert_equal("foo", AssociatedRecord.fetch_name_by_id(1))
assert_equal("foo", AssociatedRecord.fetch_name_by_item_id(1))
assert_equal("foo", AssociatedRecord.fetch_name_by_id_and_item_id(1, 1))
end

key_values = {
id: 1,
item_id: 1,
}

AssociatedRecord.cache_indexes.each do |index|
index.expire_by_key_value(key_values)
end

assert_queries(3) do
assert_equal("foo", AssociatedRecord.fetch_name_by_id(1))
assert_equal("foo", AssociatedRecord.fetch_name_by_item_id(1))
assert_equal("foo", AssociatedRecord.fetch_name_by_id_and_item_id(1, 1))
end
end

def test_expire_by_key_values_raises_exception_on_missing_key
by_id_index, by_item_id_index, by_multi_index = AssociatedRecord.cache_indexes
missing_id_error_message =
"AssociatedRecord attribute name expire_by_key_value - required fields: id. missing: id"
missing_item_id_error_message =
"AssociatedRecord attribute name expire_by_key_value - required fields: item_id. missing: item_id"
missing_id_key_in_multi_error_message =
"AssociatedRecord attribute name expire_by_key_value - required fields: id, item_id. missing: id"

missing_id_error = assert_raises(IdentityCache::MissingKeyName) do
by_id_index.expire_by_key_value({ item_id: 1 })
end
missing_item_id_error = assert_raises(IdentityCache::MissingKeyName) do
by_item_id_index.expire_by_key_value({ id: 1 })
end
missing_id_in_multi_error = assert_raises(IdentityCache::MissingKeyName) do
by_multi_index.expire_by_key_value({ item_id: 1 })
end

assert_equal(missing_id_error_message, missing_id_error.message)
assert_equal(missing_item_id_error_message, missing_item_id_error.message)
assert_equal(missing_id_key_in_multi_error_message, missing_id_in_multi_error.message)
end
end

0 comments on commit 94bb7ce

Please sign in to comment.