DEV: Add a helper method to clear every possible theme cache (#17585)

Our theme system is very complex and it can take a while to figure out how to invalidate the various types of caches that are used throughout the theme system. So, having a single helper method that invalidates everything can be useful in emergency situations where there is no time to read through the code and figure out how to clear the various caches.

Internal ticket: t64732.
This commit is contained in:
Osama Sayegh 2022-07-22 09:46:52 +03:00 committed by GitHub
parent cf5e59928e
commit 306dca3a48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 136 additions and 3 deletions

View File

@ -151,9 +151,6 @@ class Theme < ActiveRecord::Base
end
Theme.expire_site_cache!
ColorScheme.hex_cache.clear
CSP::Extension.clear_theme_extensions_cache!
SvgSprite.expire_cache
end
def self.compiler_version
@ -217,6 +214,8 @@ class Theme < ActiveRecord::Base
clear_cache!
ApplicationSerializer.expire_cache_fragment!("user_themes")
ColorScheme.hex_cache.clear
CSP::Extension.clear_theme_extensions_cache!
SvgSprite.expire_cache
end
def self.clear_default!

View File

@ -1028,4 +1028,14 @@ module Discourse
def self.allow_dev_populate?
Rails.env.development? || ENV["ALLOW_DEV_POPULATE"] == "1"
end
# warning: this method is very expensive and shouldn't be called in places
# where performance matters. it's meant to be called manually (e.g. in the
# rails console) when dealing with an emergency that requires invalidating
# theme cache
def self.clear_all_theme_cache!
ThemeField.force_recompilation!
Theme.all.each(&:update_javascript_cache!)
Theme.expire_site_cache!
end
end

View File

@ -472,4 +472,128 @@ describe Discourse do
end
end
context ".clear_all_theme_cache!" do
before do
setup_s3
SiteSetting.s3_cdn_url = "https://s3.cdn.com/gg"
stub_s3_store
end
let!(:theme) { Fabricate(:theme) }
let!(:upload) { Fabricate(:s3_image_upload) }
let!(:upload_theme_field) do
Fabricate(
:theme_field,
theme: theme,
upload: upload,
type_id: ThemeField.types[:theme_upload_var],
target_id: Theme.targets[:common],
name: "imajee",
value: "",
)
end
let!(:basic_html_field) do
Fabricate(
:theme_field,
theme: theme,
type_id: ThemeField.types[:html],
target_id: Theme.targets[:common],
name: "head_tag",
value: <<~HTML
<script type="text/discourse-plugin" version="0.1">
console.log(settings.uploads.imajee);
</script>
HTML
)
end
let!(:js_field) do
Fabricate(
:theme_field,
theme: theme,
type_id: ThemeField.types[:js],
target_id: Theme.targets[:extra_js],
name: "somefile.js",
value: <<~JS
console.log(settings.uploads.imajee);
JS
)
end
let!(:scss_field) do
Fabricate(
:theme_field,
theme: theme,
type_id: ThemeField.types[:scss],
target_id: Theme.targets[:common],
name: "scss",
value: <<~SCSS
.something { background: url($imajee); }
SCSS
)
end
it "invalidates all JS and CSS caches" do
Stylesheet::Manager.clear_theme_cache!
old_upload_url = Discourse.store.cdn_url(upload.url)
head_tag_script = Nokogiri::HTML5.fragment(
Theme.lookup_field(theme.id, :desktop, "head_tag")
).css('script').first
head_tag_js = JavascriptCache.find_by(digest: head_tag_script[:src][/\h{40}/]).content
expect(head_tag_js).to include(old_upload_url)
js_file_script = Nokogiri::HTML5.fragment(
Theme.lookup_field(theme.id, :extra_js, nil)
).css('script').first
file_js = JavascriptCache.find_by(digest: js_file_script[:src][/\h{40}/]).content
expect(file_js).to include(old_upload_url)
css_link_tag = Nokogiri::HTML5.fragment(
Stylesheet::Manager.new(theme_id: theme.id).stylesheet_link_tag(:desktop_theme, 'all')
).css('link').first
css = StylesheetCache.find_by(digest: css_link_tag[:href][/\h{40}/]).content
expect(css).to include("url(#{old_upload_url})")
SiteSetting.s3_cdn_url = "https://new.s3.cdn.com/gg"
new_upload_url = Discourse.store.cdn_url(upload.url)
head_tag_script = Nokogiri::HTML5.fragment(
Theme.lookup_field(theme.id, :desktop, "head_tag")
).css('script').first
head_tag_js = JavascriptCache.find_by(digest: head_tag_script[:src][/\h{40}/]).content
expect(head_tag_js).to include(old_upload_url)
js_file_script = Nokogiri::HTML5.fragment(
Theme.lookup_field(theme.id, :extra_js, nil)
).css('script').first
file_js = JavascriptCache.find_by(digest: js_file_script[:src][/\h{40}/]).content
expect(file_js).to include(old_upload_url)
css_link_tag = Nokogiri::HTML5.fragment(
Stylesheet::Manager.new(theme_id: theme.id).stylesheet_link_tag(:desktop_theme, 'all')
).css('link').first
css = StylesheetCache.find_by(digest: css_link_tag[:href][/\h{40}/]).content
expect(css).to include("url(#{old_upload_url})")
Discourse.clear_all_theme_cache!
head_tag_script = Nokogiri::HTML5.fragment(
Theme.lookup_field(theme.id, :desktop, "head_tag")
).css('script').first
head_tag_js = JavascriptCache.find_by(digest: head_tag_script[:src][/\h{40}/]).content
expect(head_tag_js).to include(new_upload_url)
js_file_script = Nokogiri::HTML5.fragment(
Theme.lookup_field(theme.id, :extra_js, nil)
).css('script').first
file_js = JavascriptCache.find_by(digest: js_file_script[:src][/\h{40}/]).content
expect(file_js).to include(new_upload_url)
css_link_tag = Nokogiri::HTML5.fragment(
Stylesheet::Manager.new(theme_id: theme.id).stylesheet_link_tag(:desktop_theme, 'all')
).css('link').first
css = StylesheetCache.find_by(digest: css_link_tag[:href][/\h{40}/]).content
expect(css).to include("url(#{new_upload_url})")
end
end
end