PERF: use distributed cache for site text and category slugs

This commit is contained in:
Sam 2014-11-12 09:44:32 +11:00
parent c55fa9d5c8
commit a97f2eee05
5 changed files with 43 additions and 61 deletions

View File

@ -1,3 +1,6 @@
require_dependency 'distributed_cache'
require_dependency 'sass/discourse_stylesheets'
class Category < ActiveRecord::Base class Category < ActiveRecord::Base
include Positionable include Positionable
@ -349,10 +352,26 @@ SQL
id == SiteSetting.uncategorized_category_id id == SiteSetting.uncategorized_category_id
end end
@@url_cache = DistributedCache.new('category_url')
after_save do
# parent takes part in url calculation
# any change could invalidate multiples
@@url_cache.clear
end
def url def url
url = @@url_cache[self.id]
unless url
url = "/category" url = "/category"
url << "/#{parent_category.slug}" if parent_category_id url << "/#{parent_category.slug}" if parent_category_id
url << "/#{slug}" url << "/#{slug}"
url.freeze
@@url_cache[self.id] = url
end
url
end end
# If the name changes, try and update the category definition topic too if it's # If the name changes, try and update the category definition topic too if it's
@ -366,7 +385,7 @@ SQL
end end
def publish_discourse_stylesheet def publish_discourse_stylesheet
MessageBus.publish("/discourse_stylesheet", self.name) DiscourseStylesheets.cache.clear
end end
end end

View File

@ -1,18 +1,16 @@
require_dependency 'site_text_type' require_dependency 'site_text_type'
require_dependency 'site_text_class_methods' require_dependency 'site_text_class_methods'
require_dependency 'distributed_cache'
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 after_save do
MessageBus.publish '/text_for', self.text_type SiteText.text_for_cache.clear
end end
def self.formats def self.formats

View File

@ -1,4 +1,5 @@
require_dependency 'sass/discourse_sass_compiler' require_dependency 'sass/discourse_sass_compiler'
require_dependency 'distributed_cache'
class DiscourseStylesheets class DiscourseStylesheets
@ -7,35 +8,22 @@ class DiscourseStylesheets
MANIFEST_FULL_PATH = "#{MANIFEST_DIR}/stylesheet-manifest" MANIFEST_FULL_PATH = "#{MANIFEST_DIR}/stylesheet-manifest"
@lock = Mutex.new @lock = Mutex.new
@links = {}
def self.ensure_subscribed! def self.cache
unless @subscribed @cache ||= DistributedCache.new("discourse_stylesheet")
@lock.synchronize do
MessageBus.subscribe("/discourse_stylesheet") do |message|
@lock.synchronize do
@links[message.site_id] = nil
end
end
@subscribed = true
end
end
end end
def self.stylesheet_link_tag(target = :desktop) def self.stylesheet_link_tag(target = :desktop)
ensure_subscribed! tag = cache[target]
@lock.synchronize do return tag if tag
links = (@links[RailsMultisite::ConnectionManagement.current_db] ||= {})
tag = links[target]
if !tag @lock.synchronize do
builder = self.new(target) builder = self.new(target)
builder.compile unless File.exists?(builder.stylesheet_fullpath) builder.compile unless File.exists?(builder.stylesheet_fullpath)
builder.ensure_digestless_file builder.ensure_digestless_file
tag = %[<link href="#{Rails.env.production? ? builder.stylesheet_relpath : builder.stylesheet_relpath_no_digest + '?body=1'}" media="all" rel="stylesheet" />].html_safe tag = %[<link href="#{Rails.env.production? ? builder.stylesheet_relpath : builder.stylesheet_relpath_no_digest + '?body=1'}" media="all" rel="stylesheet" />].html_safe
links[target] = tag cache[target] = tag
end
tag tag
end end

View File

@ -289,7 +289,7 @@ module SiteSettingExtension
protected protected
def clear_cache! def clear_cache!
MessageBus.publish '/text_for', 'site_settings' SiteText.text_for_cache.clear
Rails.cache.delete(SiteSettingExtension.client_settings_cache_key) Rails.cache.delete(SiteSettingExtension.client_settings_cache_key)
end end

View File

@ -15,39 +15,16 @@ module SiteTextClassMethods
@types << SiteTextType.new(text_type, format, opts) @types << SiteTextType.new(text_type, format, opts)
end end
def text_for_cache
@text_for_cache ||= DistributedCache.new("text_for_cache")
end
def text_for(text_type, replacements=nil) def text_for(text_type, replacements=nil)
text = nil text = nil
text = cached_text_for(text_type) if replacements.blank? text = text_for_cache[text_type] if replacements.blank?
text ||= uncached_text_for(text_type, replacements) text ||= uncached_text_for(text_type, replacements)
end 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) def uncached_text_for(text_type, replacements=nil)
store_cache = replacements.blank? store_cache = replacements.blank?
@ -71,7 +48,7 @@ module SiteTextClassMethods
if store_cache if store_cache
result.freeze result.freeze
store_cached_text_for(text_type, result) text_for_cache[text_type] = result
end end
result result