PERF: Eager load linkables when loading custom sidebar sections (#20490)

Not eager loading was resulting in the N+1 queries problem when
serializing with the `CurrentUserSerializer` as
`CurrentUserSerializer#sidebar_sections` serializes the sections with
`SidebarSectionSerializer` which fetches all the `SidebarUrl` records
for each `SidebarSection` record.
This commit is contained in:
Alan Guo Xiang Tan 2023-03-01 07:39:35 +08:00 committed by GitHub
parent 24188beaaf
commit 8fec1a412b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 0 deletions

View File

@ -79,6 +79,7 @@ class CurrentUserSerializer < BasicUserSerializer
def sidebar_sections
SidebarSection
.includes(sidebar_section_links: :linkable)
.where("public OR user_id = ?", object.id)
.order("(public IS TRUE) DESC")
.map { |section| SidebarSectionSerializer.new(section, root: false) }

View File

@ -7,3 +7,8 @@ Fabricator(:category_sidebar_section_link, from: :sidebar_section_link) do
end
Fabricator(:tag_sidebar_section_link, from: :sidebar_section_link) { linkable(fabricator: :tag) }
Fabricator(:custom_sidebar_section_link, from: :sidebar_section_link) do
linkable(fabricator: :sidebar_url)
sidebar_section(fabricator: :sidebar_section)
end

View File

@ -297,4 +297,53 @@ RSpec.describe CurrentUserSerializer do
end
include_examples "User Sidebar Serializer Attributes", described_class
describe "#sidebar_sections" do
fab!(:group) { Fabricate(:group) }
fab!(:sidebar_section) { Fabricate(:sidebar_section, user: user) }
before do
group.add(user)
SiteSetting.enable_custom_sidebar_sections = group.id
end
it "eager loads sidebar_urls" do
custom_sidebar_section_link_1 =
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: sidebar_section)
# warmup
described_class.new(user, scope: Guardian.new(user), root: false).as_json
initial_count =
track_sql_queries do
serialized = described_class.new(user, scope: Guardian.new(user), root: false).as_json
expect(serialized[:sidebar_sections].map { |sidebar_section| sidebar_section.id }).to eq(
[sidebar_section.id],
)
expect(serialized[:sidebar_sections].first.links.map { |link| link.id }).to eq(
[custom_sidebar_section_link_1.linkable.id],
)
end.count
custom_sidebar_section_link_2 =
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: sidebar_section)
final_count =
track_sql_queries do
serialized = described_class.new(user, scope: Guardian.new(user), root: false).as_json
expect(serialized[:sidebar_sections].map { |sidebar_section| sidebar_section.id }).to eq(
[sidebar_section.id],
)
expect(serialized[:sidebar_sections].first.links.map { |link| link.id }).to eq(
[custom_sidebar_section_link_1.linkable.id, custom_sidebar_section_link_2.linkable.id],
)
end.count
expect(initial_count).to eq(final_count)
end
end
end