2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2025-09-08 12:06:51 +08:00

PERF: Eager load Theme associations in Stylesheet Manager.

Before this change, calling `StyleSheet::Manager.stylesheet_details`
for the first time resulted in multiple queries to the database. This is
because the code was modelled in a way where each `Theme` was loaded
from the database one at a time.

This PR restructures the code such that it allows us to load all the
theme records in a single query. It also allows us to eager load the
required associations upfront. In order to achieve this, I removed the
support of loading multiple themes per request. It was initially added
to support user selectable theme components but the feature was never
completed and abandoned because it wasn't a feature that we thought was
worth building.
This commit is contained in:
Alan Guo Xiang Tan 2021-06-15 14:57:17 +08:00
parent 53dab8cf1e
commit 8e3691d537
35 changed files with 983 additions and 668 deletions

View file

@ -10,7 +10,7 @@ class ApplicationController < ActionController::Base
include Hijack
include ReadOnlyHeader
attr_reader :theme_ids
attr_reader :theme_id
serialization_scope :guardian
@ -448,35 +448,34 @@ class ApplicationController < ActionController::Base
resolve_safe_mode
return if request.env[NO_CUSTOM]
theme_ids = []
theme_id = nil
if preview_theme_id = request[:preview_theme_id]&.to_i
ids = [preview_theme_id]
theme_ids = ids if guardian.allow_themes?(ids, include_preview: true)
if (preview_theme_id = request[:preview_theme_id]&.to_i) &&
guardian.allow_themes?([preview_theme_id], include_preview: true)
theme_id = preview_theme_id
end
user_option = current_user&.user_option
if theme_ids.blank?
if theme_id.blank?
ids, seq = cookies[:theme_ids]&.split("|")
ids = ids&.split(",")&.map(&:to_i)
if ids.present? && seq && seq.to_i == user_option&.theme_key_seq.to_i
theme_ids = ids if guardian.allow_themes?(ids)
id = ids&.split(",")&.map(&:to_i)&.first
if id.present? && seq && seq.to_i == user_option&.theme_key_seq.to_i
theme_id = id if guardian.allow_themes?([id])
end
end
if theme_ids.blank?
if theme_id.blank?
ids = user_option&.theme_ids || []
theme_ids = ids if guardian.allow_themes?(ids)
theme_id = ids.first if guardian.allow_themes?(ids)
end
if theme_ids.blank? && SiteSetting.default_theme_id != -1
if guardian.allow_themes?([SiteSetting.default_theme_id])
theme_ids << SiteSetting.default_theme_id
end
if theme_id.blank? && SiteSetting.default_theme_id != -1 && guardian.allow_themes?([SiteSetting.default_theme_id])
theme_id = SiteSetting.default_theme_id
end
@theme_ids = request.env[:resolved_theme_ids] = theme_ids
@theme_id = request.env[:resolved_theme_id] = theme_id
end
def guardian
@ -635,10 +634,10 @@ class ApplicationController < ActionController::Base
target = view_context.mobile_view? ? :mobile : :desktop
data =
if @theme_ids.present?
if @theme_id.present?
{
top: Theme.lookup_field(@theme_ids, target, "after_header"),
footer: Theme.lookup_field(@theme_ids, target, "footer")
top: Theme.lookup_field(@theme_id, target, "after_header"),
footer: Theme.lookup_field(@theme_id, target, "footer")
}
else
{}
@ -943,9 +942,9 @@ class ApplicationController < ActionController::Base
end
def activated_themes_json
ids = @theme_ids&.compact
return "{}" if ids.blank?
ids = Theme.transform_ids(ids)
id = @theme_id
return "{}" if id.blank?
ids = Theme.transform_ids(id)
Theme.where(id: ids).pluck(:id, :name).to_h.to_json
end
end