我有一个现有的Model singleton方法,该方法触发要对缓存进行建模的昂贵的数据库查询。为此,我将Rails.cache.fetch()
调用封装在有问题的方法周围:
# app/models/specialist.rb
class Specialist < ActiveRecord::Base
def city
Rails.cache.fetch([self.class.name, self.id, "city"], expires_in: 23.hours) do
# expensive legacy query:
if responded?
o = offices.first
return nil if o.blank?
return o.city
elsif hospital_or_clinic_only?
(hospitals.map{ |h| h.city } + clinics.map{ |c| c.cities }).flatten.reject{ |i| i == nil }.uniq.first
elsif hospital_or_clinic_referrals_only?
(offices.map{ |o| o.city } + hospitals.map{ |h| h.city } + clinics.map{ |c| c.cities }).flatten.reject{ |c| c.blank? }.uniq.first
else
nil
end
end
end
end
.city
对所有记录执行通常需要16秒;使用此Rails.cache.fetch
块,它仅下降到7秒,因为一半的记录仍在触发数据库调用。
当我调查时发现,该city
方法返回时nil
,Rails.cache不会将结果写入memcache中-这意味着尽管“缓存”了我的一半专家记录仍会触发昂贵的数据库查找
我如何在使用Memcache时强制Rails.cache.fetch
存储的值,nil
以便不会触发另一个再次查找nil的数据库查找?
一种解决方案是使用NullObject,如下所示:
class Specialist
NullData = Struct.new(nil)
def city
result = Rails.cache.fetch([self.class.name, self.id, "city"], expires_in: 23.hours) do
if responded?
..
else
NullData.new()
end
result.is_a?(NullData) ? nil : result
end
end
这样,您将创建一个可以缓存的空对象。然后,当您返回时,请检查是否已存储了一个空对象,在这种情况下,您将返回nil(以确保您不会破坏依赖于您的方法返回nil的旧代码),否则您将返回缓存的内容。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句