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