PERF: cache all site_text in memory
This commit is contained in:
parent
b2af49251d
commit
4e85fc9dae
|
@ -2,11 +2,19 @@ require_dependency 'site_text_type'
|
||||||
require_dependency 'site_text_class_methods'
|
require_dependency 'site_text_class_methods'
|
||||||
|
|
||||||
class SiteText < ActiveRecord::Base
|
class SiteText < ActiveRecord::Base
|
||||||
|
|
||||||
|
# needed for site text class methods
|
||||||
|
@mutex = Mutex.new
|
||||||
|
@text_for_cache = {}
|
||||||
extend SiteTextClassMethods
|
extend SiteTextClassMethods
|
||||||
self.primary_key = 'text_type'
|
self.primary_key = 'text_type'
|
||||||
|
|
||||||
validates_presence_of :value
|
validates_presence_of :value
|
||||||
|
|
||||||
|
after_save do
|
||||||
|
MessageBus.publish '/text_for', self.text_type
|
||||||
|
end
|
||||||
|
|
||||||
def self.formats
|
def self.formats
|
||||||
@formats ||= Enum.new(:plain, :markdown, :html, :css)
|
@formats ||= Enum.new(:plain, :markdown, :html, :css)
|
||||||
end
|
end
|
||||||
|
|
|
@ -289,6 +289,7 @@ module SiteSettingExtension
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def clear_cache!
|
def clear_cache!
|
||||||
|
MessageBus.publish '/text_for', 'site_settings'
|
||||||
Rails.cache.delete(SiteSettingExtension.client_settings_cache_key)
|
Rails.cache.delete(SiteSettingExtension.client_settings_cache_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,41 @@ module SiteTextClassMethods
|
||||||
end
|
end
|
||||||
|
|
||||||
def text_for(text_type, replacements=nil)
|
def text_for(text_type, replacements=nil)
|
||||||
|
text = nil
|
||||||
|
text = cached_text_for(text_type) if replacements.blank?
|
||||||
|
text ||= uncached_text_for(text_type, replacements)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cached_text_for(text_type)
|
||||||
|
ensure_subscribed!
|
||||||
|
@mutex.synchronize do
|
||||||
|
cache = @text_for_cache[RailsMultisite::ConnectionManagement.current_db]
|
||||||
|
cache[text_type] if cache
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def store_cached_text_for(text_type, result)
|
||||||
|
ensure_subscribed!
|
||||||
|
@mutex.synchronize do
|
||||||
|
cache = (@text_for_cache[RailsMultisite::ConnectionManagement.current_db] ||= {})
|
||||||
|
cache[text_type] = result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_subscribed!
|
||||||
|
return if @subscribed
|
||||||
|
@mutex.synchronize do
|
||||||
|
MessageBus.subscribe("/text_for") do |message|
|
||||||
|
@mutex.synchronize do
|
||||||
|
@text_for_cache[message.site_id] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def uncached_text_for(text_type, replacements=nil)
|
||||||
|
store_cache = replacements.blank?
|
||||||
|
|
||||||
replacements ||= {}
|
replacements ||= {}
|
||||||
replacements = {site_name: SiteSetting.title}.merge!(replacements)
|
replacements = {site_name: SiteSetting.title}.merge!(replacements)
|
||||||
replacements = SiteSetting.settings_hash.merge!(replacements)
|
replacements = SiteSetting.settings_hash.merge!(replacements)
|
||||||
|
@ -34,6 +69,11 @@ module SiteTextClassMethods
|
||||||
replacements[m[2..-2].to_sym] || m
|
replacements[m[2..-2].to_sym] || m
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if store_cache
|
||||||
|
result.freeze
|
||||||
|
store_cached_text_for(text_type, result)
|
||||||
|
end
|
||||||
|
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,29 @@ describe SiteText do
|
||||||
describe "#text_for" do
|
describe "#text_for" do
|
||||||
|
|
||||||
it "returns an empty string for a missing text_type" do
|
it "returns an empty string for a missing text_type" do
|
||||||
SiteText.text_for('breaking.bad').should == ""
|
SiteText.text_for('something_random').should == ""
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns the default value for a text` type with a default" do
|
it "returns the default value for a text` type with a default" do
|
||||||
SiteText.text_for("usage_tips").should be_present
|
SiteText.text_for("usage_tips").should be_present
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "correctly expires and bypasses cache" do
|
||||||
|
SiteSetting.enable_sso = false
|
||||||
|
text = SiteText.create!(text_type: "got.sso", value: "got sso: %{enable_sso}")
|
||||||
|
SiteText.text_for("got.sso").should == "got sso: false"
|
||||||
|
SiteText.text_for("got.sso").frozen? == true
|
||||||
|
|
||||||
|
SiteSetting.enable_sso = true
|
||||||
|
SiteText.text_for("got.sso").should == "got sso: true"
|
||||||
|
|
||||||
|
text.value = "I gots sso: %{enable_sso}"
|
||||||
|
text.save!
|
||||||
|
|
||||||
|
SiteText.text_for("got.sso").should == "I gots sso: true"
|
||||||
|
SiteText.text_for("got.sso", enable_sso: "frog").should == "I gots sso: frog"
|
||||||
|
end
|
||||||
|
|
||||||
context "without replacements" do
|
context "without replacements" do
|
||||||
let!(:site_text) { Fabricate(:site_text_basic) }
|
let!(:site_text) { Fabricate(:site_text_basic) }
|
||||||
|
|
||||||
|
@ -46,12 +62,12 @@ describe SiteText do
|
||||||
let!(:site_text) { Fabricate(:site_text_site_setting) }
|
let!(:site_text) { Fabricate(:site_text_site_setting) }
|
||||||
|
|
||||||
it "replaces site_settings by default" do
|
it "replaces site_settings by default" do
|
||||||
SiteSetting.stubs(:title).returns("Evil Trout")
|
SiteSetting.title = "Evil Trout"
|
||||||
SiteText.text_for('site.replacement').should == "Evil Trout is evil."
|
SiteText.text_for('site.replacement').should == "Evil Trout is evil."
|
||||||
end
|
end
|
||||||
|
|
||||||
it "allows us to override the default site settings" do
|
it "allows us to override the default site settings" do
|
||||||
SiteSetting.stubs(:title).returns("Evil Trout")
|
SiteSetting.title = "Evil Trout"
|
||||||
SiteText.text_for('site.replacement', title: 'Good Tuna').should == "Good Tuna is evil."
|
SiteText.text_for('site.replacement', title: 'Good Tuna').should == "Good Tuna is evil."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue