From cdffcfbcfdb9cb89bcde8283f4923ced4eb5059c Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 9 Dec 2013 01:15:57 -0600 Subject: [PATCH] TIL item proxies can read from the cache in bulk --- app/models/item/proxy.rb | 24 ++++++++++-------------- app/models/item/proxy_array.rb | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app/models/item/proxy.rb b/app/models/item/proxy.rb index 0a2967cb..20b16178 100644 --- a/app/models/item/proxy.rb +++ b/app/models/item/proxy.rb @@ -23,14 +23,6 @@ class Item end end - def cached?(type, name) - # TODO: is there a way to cache nil? Right now we treat is as a miss. - # We eagerly read the cache rather than just check if the value exists, - # which will usually cut down on cache requests. - @known_outputs[type][name] ||= Rails.cache.read(fragment_key(type, name)) - !@known_outputs[type][name].nil? - end - def owned? @owned end @@ -44,6 +36,16 @@ class Item @wanted end + def fragment_key(type, name) + prefix = type == :partial ? 'views/' : '' + base = localize_fragment_key("items/#{@id}##{name}", I18n.locale) + prefix + base + end + + def set_known_output(type, name, value) + @known_outputs[type][name] = value + end + private def cache_method(method_name, *args, &block) @@ -58,11 +60,5 @@ class Item def item @item ||= Item.find(@id) end - - def fragment_key(type, name) - prefix = type == :partial ? 'views/' : '' - base = localize_fragment_key("items/#{@id}##{name}", I18n.locale) - prefix + base - end end end \ No newline at end of file diff --git a/app/models/item/proxy_array.rb b/app/models/item/proxy_array.rb index 2f707587..f1174736 100644 --- a/app/models/item/proxy_array.rb +++ b/app/models/item/proxy_array.rb @@ -27,11 +27,21 @@ class Item private def prepare(type, name) - missed_proxies_by_id = self. - reject { |p| p.cached?(type, name) }. - index_by(&:id) item_scope = SCOPES[type][name] raise "unexpected #{type} #{name.inspect}" unless item_scope + + # Try to read all values from the cache in one go, setting the proxy + # values as we go along. Delete successfully set proxies, so that + # everything left in proxies_by_key in the end is known to be a miss. + proxies_by_key = {} + self.each { |p| proxies_by_key[p.fragment_key(type, name)] = p } + Rails.cache.read_multi(*proxies_by_key.keys).each { |k, v| + proxies_by_key.delete(k).set_known_output(type, name, v) + } + + missed_proxies = proxies_by_key.values + missed_proxies_by_id = missed_proxies.index_by(&:id) + item_scope.find(missed_proxies_by_id.keys).each do |item| missed_proxies_by_id[item.id].item = item end