class IknowCache::CacheGroup
def delete_all(key, parent_path: nil)
Clear this key in all Caches in this CacheGroup.
def delete_all(key, parent_path: nil) @caches.each do |cache| cache.delete(key, parent_path: parent_path) end @children.each do |child_group| child_group.invalidate_cache_group(key) end end
def initialize(parent, name, key_name, default_options, static_version)
def initialize(parent, name, key_name, default_options, static_version) @parent = parent @name = name @key_name = key_name @key = Struct.new(*parent.try { |p| p.key.members }, key_name) @default_options = IknowCache.merge_options(parent&.default_options, default_options).try { |x| x.dup.freeze } @static_version = static_version @caches = [] @children = [] end
def invalidate_cache_group(parent_key = nil)
Clear all keys in this cache group (for the given parent),
def invalidate_cache_group(parent_key = nil) parent_path = self.parent_path(parent_key) IknowCache.cache.increment(version_path_string(parent_path)) end
def parent_path(parent_key = nil)
def parent_path(parent_key = nil) if parent.nil? ROOT_PATH else parent.path(parent_key) end end
def parent_path_multi(parent_keys = nil)
def parent_path_multi(parent_keys = nil) if parent.nil? parent_keys.each_with_object({}) { |k, h| h[k] = ROOT_PATH } else parent.path_multi(parent_keys) end end
def path(key, parent_path = nil)
Fetch the path for this cache. We allow the parent_path to be precomputed
def path(key, parent_path = nil) if key.nil? || key[self.key_name].nil? raise ArgumentError.new("Missing required key '#{self.key_name}' for cache '#{self.name}'") end key_value = key[self.key_name] parent_path ||= self.parent_path(key) version = self.version(parent_path) path_string(parent_path, version, key_value) end
def path_multi(keys)
def path_multi(keys) # compute parent path for each key parent_paths = self.parent_path_multi(keys) # and versions for each parent path versions = self.version_multi(parent_paths.values.uniq) # update parent_paths with our paths keys.each do |key| parent_path = parent_paths[key] version = versions[parent_path] key_value = key[self.key_name] unless key_value raise ArgumentError.new("Required cache key missing: #{self.key_name}") end parent_paths[key] = path_string(parent_path, version, key_value) end parent_paths end
def path_string(parent_path, version, value)
def path_string(parent_path, version, value) "#{parent_path}/#{name}/#{@static_version}/#{version}/#{value}" end
def register_cache(name, static_version: nil, cache_options: nil)
def register_cache(name, static_version: nil, cache_options: nil) c = Cache.new(self, name, static_version, cache_options) @caches << c c end
def register_child_group(name, key_name, default_options: nil, static_version: 1)
def register_child_group(name, key_name, default_options: nil, static_version: 1) group = CacheGroup.new(self, name, key_name, default_options, static_version) @children << group yield group if block_given? group end
def version(parent_path)
def version(parent_path) IknowCache.cache.fetch(version_path_string(parent_path), raw: true) { 1 } end
def version_multi(parent_paths)
def version_multi(parent_paths) # compute version paths version_by_pp = parent_paths.each_with_object({}) { |pp, h| h[pp] = version_path_string(pp) } version_paths = version_by_pp.values # look up versions in cache versions = IknowCache.cache.read_multi(*version_paths, raw: true) version_paths.each do |vp| next if versions.has_key?(vp) versions[vp] = IknowCache.cache.fetch(vp, raw: true) { 1 } end # swap in the versions parent_paths.each do |pp| vp = version_by_pp[pp] version = versions[vp] version_by_pp[pp] = version end version_by_pp end
def version_path_string(parent_path)
def version_path_string(parent_path) "#{parent_path}/#{name}/_version" end