module ActiveSupport::Cache::Strategy::LocalCache
def bypass_local_cache(&block)
def bypass_local_cache(&block) use_temporary_local_cache(nil, &block) end
def cleanup(options = nil) # :nodoc:
def cleanup(options = nil) # :nodoc: return super unless cache = local_cache cache.clear(options) super end
def clear(options = nil) # :nodoc:
def clear(options = nil) # :nodoc: return super unless cache = local_cache cache.clear(options) super end
def decrement(name, amount = 1, **options) # :nodoc:
def decrement(name, amount = 1, **options) # :nodoc: return super unless local_cache value = bypass_local_cache { super } write_cache_value(name, value, raw: true, **options) value end
def delete_entry(key, **)
def delete_entry(key, **) local_cache.delete_entry(key) if local_cache super end
def delete_matched(matcher, options = nil) # :nodoc:
def delete_matched(matcher, options = nil) # :nodoc: return super unless cache = local_cache cache.clear(options) super end
def fetch_multi(*names, &block) # :nodoc:
def fetch_multi(*names, &block) # :nodoc: return super if local_cache.nil? || names.empty? options = names.extract_options! options = merged_options(options) keys_to_names = names.index_by { |name| normalize_key(name, options) } local_entries = local_cache.read_multi_entries(keys_to_names.keys) results = local_entries.each_with_object({}) do |(key, value), result| # If we recorded a miss in the local cache, `#fetch_multi` will forward # that key to the real store, and the entry will be replaced # local_cache.delete_entry(key) next if value.nil? entry = deserialize_entry(value, **options) normalized_key = keys_to_names[key] if entry.nil? result[normalized_key] = nil elsif entry.expired? || entry.mismatched?(normalize_version(normalized_key, options)) local_cache.delete_entry(key) else result[normalized_key] = entry.value end end if results.size < names.size results.merge!(super(*(names - results.keys), options, &block)) end results end
def increment(name, amount = 1, **options) # :nodoc:
def increment(name, amount = 1, **options) # :nodoc: return super unless local_cache value = bypass_local_cache { super } write_cache_value(name, value, raw: true, **options) value end
def local_cache
def local_cache LocalCacheRegistry.cache_for(local_cache_key) end
def local_cache_key
def local_cache_key @local_cache_key ||= "#{self.class.name.underscore}_local_cache_#{object_id}".gsub(/[\/-]/, "_").to_sym end
def middleware
Middleware class can be inserted as a Rack handler to be local cache for the
def middleware @middleware ||= Middleware.new( "ActiveSupport::Cache::Strategy::LocalCache", local_cache_key) end
def read_multi_entries(names, **options)
def read_multi_entries(names, **options) return super unless local_cache keys_to_names = names.index_by { |name| normalize_key(name, options) } local_entries = local_cache.read_multi_entries(keys_to_names.keys) results = local_entries.each_with_object({}) do |(key, value), result| next if value.nil? # recorded cache miss entry = deserialize_entry(value, **options) normalized_key = keys_to_names[key] if entry.nil? result[normalized_key] = nil elsif entry.expired? || entry.mismatched?(normalize_version(normalized_key, options)) local_cache.delete_entry(key) else result[normalized_key] = entry.value end end if results.size < names.size results.merge!(super(names - results.keys, **options)) end results end
def read_serialized_entry(key, raw: false, **options)
def read_serialized_entry(key, raw: false, **options) if cache = local_cache hit = true entry = cache.fetch_entry(key) do hit = false super end options[:event][:store] = cache.class.name if hit && options[:event] entry else super end end
def use_temporary_local_cache(temporary_cache)
def use_temporary_local_cache(temporary_cache) save_cache = LocalCacheRegistry.cache_for(local_cache_key) begin LocalCacheRegistry.set_cache_for(local_cache_key, temporary_cache) yield ensure LocalCacheRegistry.set_cache_for(local_cache_key, save_cache) end end
def with_local_cache(&block)
def with_local_cache(&block) use_temporary_local_cache(LocalStore.new, &block) end
def write_cache_value(name, value, **options)
def write_cache_value(name, value, **options) name = normalize_key(name, options) cache = local_cache if value cache.write_entry(name, serialize_entry(new_entry(value, **options), **options)) else cache.delete_entry(name) end end
def write_serialized_entry(key, payload, **)
def write_serialized_entry(key, payload, **) if return_value = super local_cache.write_entry(key, payload) if local_cache else local_cache.delete_entry(key) if local_cache end return_value end