lib/flipper/adapters/redis_cache.rb in flipper-redis-1.2.2 vs lib/flipper/adapters/redis_cache.rb in flipper-redis-1.3.0.pre
- old
+ new
@@ -1,148 +1,46 @@
require 'redis'
require 'flipper'
+require 'flipper/adapters/cache_base'
module Flipper
module Adapters
# Public: Adapter that wraps another adapter with the ability to cache
- # adapter calls in Redis
- class RedisCache
- include ::Flipper::Adapter
-
- # Internal
- attr_reader :cache
-
- # Public
- def initialize(adapter, cache, ttl = 3600)
- @adapter = adapter
- @cache = cache
- @ttl = ttl
-
- @version = 'v1'.freeze
- @namespace = "flipper/#{@version}".freeze
- @features_key = "#{@namespace}/features".freeze
- @get_all_key = "#{@namespace}/get_all".freeze
+ # adapter calls in Redis.
+ class RedisCache < CacheBase
+ def initialize(adapter, cache, ttl = 3600, prefix: nil)
+ super
end
- # Public
- def features
- read_feature_keys
- end
-
- # Public
- def add(feature)
- result = @adapter.add(feature)
- @cache.del(@features_key)
- result
- end
-
- # Public
- def remove(feature)
- result = @adapter.remove(feature)
- @cache.del(@features_key)
- @cache.del(key_for(feature.key))
- result
- end
-
- # Public
- def clear(feature)
- result = @adapter.clear(feature)
- @cache.del(key_for(feature.key))
- result
- end
-
- # Public
- def get(feature)
- fetch(key_for(feature.key)) do
- @adapter.get(feature)
- end
- end
-
- def get_multi(features)
- read_many_features(features)
- end
-
- def get_all
- if @cache.setnx(@get_all_key, Time.now.to_i)
- @cache.expire(@get_all_key, @ttl)
- response = @adapter.get_all
- response.each do |key, value|
- set_with_ttl key_for(key), value
- end
- set_with_ttl @features_key, response.keys.to_set
- response
- else
- features = read_feature_keys.map { |key| Flipper::Feature.new(key, self) }
- read_many_features(features)
- end
- end
-
- # Public
- def enable(feature, gate, thing)
- result = @adapter.enable(feature, gate, thing)
- @cache.del(key_for(feature.key))
- result
- end
-
- # Public
- def disable(feature, gate, thing)
- result = @adapter.disable(feature, gate, thing)
- @cache.del(key_for(feature.key))
- result
- end
-
private
- def key_for(key)
- "#{@namespace}/feature/#{key}"
- end
-
- def read_feature_keys
- fetch(@features_key) { @adapter.features }
- end
-
- def read_many_features(features)
- keys = features.map(&:key)
- cache_result = Hash[keys.zip(multi_cache_get(keys))]
- uncached_features = features.reject { |feature| cache_result[feature.key] }
-
- if uncached_features.any?
- response = @adapter.get_multi(uncached_features)
- response.each do |key, value|
- set_with_ttl(key_for(key), value)
- cache_result[key] = value
- end
- end
-
- result = {}
- features.each do |feature|
- result[feature.key] = cache_result[feature.key]
- end
- result
- end
-
- def fetch(cache_key)
- cached = @cache.get(cache_key)
+ def cache_fetch(key, &block)
+ cached = @cache.get(key)
if cached
Marshal.load(cached)
else
to_cache = yield
- set_with_ttl(cache_key, to_cache)
+ cache_write key, to_cache
to_cache
end
end
- def set_with_ttl(key, value)
- @cache.setex(key, @ttl, Marshal.dump(value))
- end
+ def cache_read_multi(keys)
+ return {} if keys.empty?
- def multi_cache_get(keys)
- return [] if keys.empty?
-
- cache_keys = keys.map { |key| key_for(key) }
- @cache.mget(*cache_keys).map do |value|
+ values = @cache.mget(*keys).map do |value|
value ? Marshal.load(value) : nil
end
+
+ Hash[keys.zip(values)]
+ end
+
+ def cache_write(key, value)
+ @cache.setex(key, @ttl, Marshal.dump(value))
+ end
+
+ def cache_delete(key)
+ @cache.del(key)
end
end
end
end