FIX: SiteSettings defaults cache leaking across multisite.

This commit is contained in:
Guo Xiang Tan 2017-08-07 15:15:32 +09:00
parent f496302c2c
commit c5850422f0
3 changed files with 31 additions and 31 deletions

View File

@ -66,9 +66,11 @@ module SiteSettingExtension
def setting(name_arg, default = nil, opts = {}) def setting(name_arg, default = nil, opts = {})
name = name_arg.to_sym name = name_arg.to_sym
mutex.synchronize do mutex.synchronize do
defaults.load_setting(name, defaults.load_setting(
default, name,
opts.extract!(*SiteSettings::DefaultsProvider::CONSUMED_OPTS)) default,
opts.extract!(*SiteSettings::DefaultsProvider::CONSUMED_OPTS)
)
categories[name] = opts[:category] || :uncategorized categories[name] = opts[:category] || :uncategorized
@ -97,8 +99,10 @@ module SiteSettingExtension
previews[name] = opts[:preview] previews[name] = opts[:preview]
end end
type_supervisor.load_setting(name, type_supervisor.load_setting(
opts.extract!(*SiteSettings::TypeSupervisor::CONSUMED_OPTS)) name,
opts.extract!(*SiteSettings::TypeSupervisor::CONSUMED_OPTS)
)
setup_methods(name) setup_methods(name)
end end
@ -164,7 +168,7 @@ module SiteSettingExtension
defaults_view = defaults.all defaults_view = defaults.all
# add locale default and defaults based on default_locale, cause they are cached # add locale default and defaults based on default_locale, cause they are cached
new_hash = defaults_view.merge(new_hash) new_hash = defaults_view.merge!(new_hash)
# add shadowed # add shadowed
shadowed_settings.each { |ss| new_hash[ss] = GlobalSetting.send(ss) } shadowed_settings.each { |ss| new_hash[ss] = GlobalSetting.send(ss) }

View File

@ -12,11 +12,10 @@ class SiteSettings::DefaultsProvider
def initialize(site_setting) def initialize(site_setting)
@site_setting = site_setting @site_setting = site_setting
@site_setting.refresh_settings << DEFAULT_LOCALE_KEY @site_setting.refresh_settings << DEFAULT_LOCALE_KEY
@cached = {}
@defaults = {} @defaults = {}
@defaults[DEFAULT_LOCALE.to_sym] = {} @defaults[DEFAULT_LOCALE.to_sym] = {}
@site_locale = {}
@site_locales = {}
refresh_site_locale! refresh_site_locale!
end end
@ -31,7 +30,6 @@ class SiteSettings::DefaultsProvider
@defaults[locale][name] = v @defaults[locale][name] = v
end end
end end
refresh_cache!
end end
def db_all def db_all
@ -39,12 +37,14 @@ class SiteSettings::DefaultsProvider
end end
def all def all
@cached @defaults[DEFAULT_LOCALE.to_sym].merge(@defaults[self.site_locale.to_sym] || {})
end end
def get(name) def get(name)
@cached[name.to_sym] @defaults.dig(self.site_locale.to_sym, name.to_sym) ||
@defaults.dig(DEFAULT_LOCALE.to_sym, name.to_sym)
end end
alias [] get
# Used to override site settings in dev/test env # Used to override site settings in dev/test env
def set_regardless_of_locale(name, value) def set_regardless_of_locale(name, value)
@ -53,34 +53,34 @@ class SiteSettings::DefaultsProvider
@defaults.each { |_, hash| hash.delete(name) } @defaults.each { |_, hash| hash.delete(name) }
@defaults[DEFAULT_LOCALE.to_sym][name] = value @defaults[DEFAULT_LOCALE.to_sym][name] = value
value, type = @site_setting.type_supervisor.to_db_value(name, value) value, type = @site_setting.type_supervisor.to_db_value(name, value)
@cached[name] = @site_setting.type_supervisor.to_rb_value(name, value, type) @defaults[self.site_locale.to_sym][name] = @site_setting.type_supervisor.to_rb_value(name, value, type)
else else
raise ArgumentError.new("No setting named '#{name}' exists") raise ArgumentError.new("No setting named '#{name}' exists")
end end
end end
alias [] get
def site_locale def site_locale
@site_locale[current_db] @site_locales[current_db]
end end
def site_locale=(val) def site_locale=(val)
val = val.to_s val = val.to_s
raise Discourse::InvalidParameters.new(:value) unless LocaleSiteSetting.valid_value?(val) raise Discourse::InvalidParameters.new(:value) unless LocaleSiteSetting.valid_value?(val)
if val != @site_locale[current_db] if val != @site_locales[current_db]
@site_setting.provider.save(DEFAULT_LOCALE_KEY, val, SiteSetting.types[:string]) @site_setting.provider.save(DEFAULT_LOCALE_KEY, val, SiteSetting.types[:string])
refresh_site_locale! refresh_site_locale!
@site_setting.refresh! @site_setting.refresh!
Discourse.request_refresh! Discourse.request_refresh!
end end
@site_locale[current_db] @site_locales[current_db]
end end
def each def each(&block)
@cached.each { |k, v| yield k.to_sym, v } self.all.each do |key, value|
block.call(key.to_sym, value)
end
end end
def locale_setting_hash def locale_setting_hash
@ -91,7 +91,7 @@ class SiteSettings::DefaultsProvider
description: @site_setting.description(DEFAULT_LOCALE_KEY), description: @site_setting.description(DEFAULT_LOCALE_KEY),
type: SiteSetting.types[SiteSetting.types[:enum]], type: SiteSetting.types[SiteSetting.types[:enum]],
preview: nil, preview: nil,
value: @site_locale[current_db], value: @site_locales[current_db],
valid_values: LocaleSiteSetting.values, valid_values: LocaleSiteSetting.values,
translate_names: LocaleSiteSetting.translate_names? translate_names: LocaleSiteSetting.translate_names?
} }
@ -99,7 +99,7 @@ class SiteSettings::DefaultsProvider
def refresh_site_locale! def refresh_site_locale!
RailsMultisite::ConnectionManagement.each_connection do |db| RailsMultisite::ConnectionManagement.each_connection do |db|
@site_locale[db] = @site_locales[db] =
if GlobalSetting.respond_to?(DEFAULT_LOCALE_KEY) && if GlobalSetting.respond_to?(DEFAULT_LOCALE_KEY) &&
(global_val = GlobalSetting.send(DEFAULT_LOCALE_KEY)) && (global_val = GlobalSetting.send(DEFAULT_LOCALE_KEY)) &&
!global_val.blank? !global_val.blank?
@ -110,8 +110,7 @@ class SiteSettings::DefaultsProvider
DEFAULT_LOCALE DEFAULT_LOCALE
end end
refresh_cache! @site_locales[db]
@site_locale[db]
end end
end end
@ -121,12 +120,9 @@ class SiteSettings::DefaultsProvider
private private
def has_key?(key) def has_key?(name)
@cached.key?(key) || key == DEFAULT_LOCALE_KEY @defaults[self.site_locale.to_sym]&.key?(name) ||
end @defaults[DEFAULT_LOCALE.to_sym].key?(name) || name == DEFAULT_LOCALE_KEY
def refresh_cache!
@cached = @defaults[DEFAULT_LOCALE.to_sym].merge(@defaults.fetch(@site_locale[current_db].to_sym, {}))
end end
def current_db def current_db

View File

@ -40,7 +40,7 @@ describe SiteSettings::DefaultsProvider do
end end
describe 'expose default cache according to locale' do describe 'expose default cache according to locale' do
before(:each) do before do
settings.setting(:test_override, 'default', locale_default: { zh_CN: 'cn' }) settings.setting(:test_override, 'default', locale_default: { zh_CN: 'cn' })
settings.setting(:test_default, 'test', regex: '^\S+$') settings.setting(:test_default, 'test', regex: '^\S+$')
settings.refresh! settings.refresh!