lib/determinator/cache/fetch_wrapper.rb in determinator-2.0.0 vs lib/determinator/cache/fetch_wrapper.rb in determinator-2.1.0
- old
+ new
@@ -1,20 +1,58 @@
module Determinator
module Cache
class FetchWrapper
- # @param cache [#fetch] An instance of a cache class which implements #fetch like ActiveSupport::Cache does
- def initialize(cache)
- @cache = cache
+ # @param *caches [ActiveSupport::Cache] If a list then the head of the the
+ # list should will be checked before the tail. If the head is empty but
+ # the tail is not then the head will be filled with the value of the tail.
+ def initialize(*caches)
+ @caches = caches
end
+ # Call walks through each cache, returning a value if the item exists in
+ # any cache, otherwise popularing each cache with the value of yield.
def call(feature_name)
- @cache.fetch(key(feature_name)) { yield }
+ value = read_and_upfill(feature_name)
+ # nil is an acceptable value in the case of a missing feature definition
+ return nil if value.nil?
+ return value if value != false
+
+ value_to_write = yield
+ @caches.each do |cache|
+ cache.write(key(feature_name), value_to_write)
+ end
+ return value_to_write
end
+ def expire(feature_name)
+ @caches.each{ |c| c.delete(key(feature_name)) }
+ end
+
private
def key(feature_name)
"determinator:feature_cache:#{feature_name}"
+ end
+
+ # Walks through the list of caches, returning the first stored value.
+ #
+ # If a value is found in a cache after the first then all caches earlier
+ # in that list will be backfilled.
+ #
+ # @param url [String] a feature name
+ # @return [false, nil, Feature] false when no value is found, otherwise
+ # the value stored in the cache (including nil)
+ def read_and_upfill(feature_name)
+ @caches.each.with_index do |cache, index|
+ if cache.exist?(key(feature_name))
+ value = cache.read(key(feature_name))
+ @caches[0...index].each do |cache|
+ cache.write(key(feature_name), value)
+ end
+ return value
+ end
+ end
+ return false
end
end
end
end