lib/looksist/redis_service.rb in looksist-0.0.8 vs lib/looksist/redis_service.rb in looksist-0.1.0
- old
+ new
@@ -1,51 +1,55 @@
module Looksist
class RedisService
+
attr_accessor :client, :buffer_size, :cache
- def self.instance
- @_instance_ ||= new
- @_instance_.cache ||= {}
- yield @_instance_ if block_given?
- @_instance_.buffer_size ||= 50000
- @_instance_
+ class << self
+ private :new
+
+ def instance
+ @this ||= new
+ @this.buffer_size = 50000
+ yield @this if block_given?
+ @this.cache = SafeLruCache.new(@this.buffer_size)
+ @this
+ end
end
- def method_missing(m, *args, &block)
- if m.to_s.ends_with?("_for")
- entity = m.to_s.gsub('_for', '')
- args.first.is_a?(Array) ? find_all(entity, args.first) : find(entity, args.first)
+ def method_missing(name, *args, &block)
+ if name.to_s.ends_with?("_for")
+ entity = name.to_s.gsub('_for','')
+ first_arg = args.first
+ first_arg.is_a?(Array) ? find_all(entity, first_arg) : find(entity, first_arg)
else
- super(m, args)
+ super(name, args)
end
end
+ def flush_cache!
+ @cache.clear
+ end
+
private
+ def find_all(entity, ids)
+ raise 'Buffer overflow! Increase buffer size' if ids.length > @buffer_size
+ keys = ids.collect { |id| redis_key(entity, id) }
+ missed_keys = (keys - @cache.keys).uniq
+ values = @client.mget missed_keys
+ @cache.merge!(Hash[*missed_keys.zip(values).flatten])
+ @cache.mslice(keys)
+ end
+
def find(entity, id)
key = redis_key(entity, id)
- hit_or_miss(key) do
+ fetch(key) do
@client.get(key)
end
end
-
- def find_all(entity, ids)
- @client.pipelined do
- ids.uniq.each do |id|
- find(entity, id)
- end
- end
- ids.each_with_object([]) { |k, acc| acc << cache[redis_key(entity, k)].value }
- end
-
- def hit_or_miss(key, &block)
- @cache[key] ||= lru(&block)
- end
-
- def lru
- @cache.shift if @cache.length >= @buffer_size
- yield
+ def fetch(key, &block)
+ @cache[key] ||= block.call
end
def redis_key(entity, id)
"#{entity.pluralize}/#{id}"
end