DEV: Change categories#index loading strategy (#25232)

The old strategy used to load 25 categories at a time, including the
subcategories. The new strategy loads 20 parent categories and at most
5 subcategories for each parent category, for a maximum of 120
categories in total.
This commit is contained in:
Bianca Nenciu 2024-01-17 17:18:01 +02:00 committed by GitHub
parent ec1905cf6f
commit 4cfc0e231a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 2 deletions

View File

@ -1,7 +1,8 @@
# frozen_string_literal: true
class CategoryList
CATEGORIES_PER_PAGE = 25
CATEGORIES_PER_PAGE = 20
SUBCATEGORIES_PER_CATEGORY = 5
include ActiveModel::Serialization
@ -138,7 +139,11 @@ class CategoryList
if SiteSetting.lazy_load_categories
page = [1, @options[:page].to_i].max
query = query.limit(CATEGORIES_PER_PAGE).offset((page - 1) * CATEGORIES_PER_PAGE)
query =
query
.where(parent_category_id: nil)
.limit(CATEGORIES_PER_PAGE)
.offset((page - 1) * CATEGORIES_PER_PAGE)
end
query =
@ -146,6 +151,20 @@ class CategoryList
@categories = query.to_a
if SiteSetting.lazy_load_categories
categories_with_rownum =
Category
.secured(@guardian)
.select(:id, "ROW_NUMBER() OVER (PARTITION BY parent_category_id) rownum")
.where(parent_category_id: @categories.map { |c| c.id })
@categories +=
Category.where(
"id IN (WITH cte AS (#{categories_with_rownum.to_sql}) SELECT id FROM cte WHERE rownum <= ?)",
SUBCATEGORIES_PER_CATEGORY,
)
end
if Site.preloaded_category_custom_fields.any?
Category.preload_custom_fields(@categories, Site.preloaded_category_custom_fields)
end

View File

@ -387,5 +387,25 @@ RSpec.describe CategoryList do
category_list.categories.find { |c| c.id == category.id }.subcategory_ids,
).to contain_exactly(subcategory.id)
end
it "returns at most SUBCATEGORIES_PER_CATEGORY subcategories" do
subcategory_2 = Fabricate(:category, user: admin, parent_category: category)
category_list =
stub_const(CategoryList, "SUBCATEGORIES_PER_CATEGORY", 1) do
CategoryList.new(Guardian.new(user), include_topics: true)
end
expect(category_list.categories.size).to eq(3)
uncategorized_category = Category.find(SiteSetting.uncategorized_category_id)
expect(category_list.categories).to include(uncategorized_category)
expect(category_list.categories).to include(category)
expect(category_list.categories).to include(subcategory).or include(subcategory_2)
expect(category_list.categories.map(&:parent_category_id)).to contain_exactly(
nil,
nil,
category.id,
)
end
end
end