From b917e6d5e3355f61a0bfeb2feef279b53b7bcd4a Mon Sep 17 00:00:00 2001
From: Siddharth Dungarwal <sdungarwal@gitlab.com>
Date: Mon, 10 Apr 2023 20:04:31 +0000
Subject: [PATCH] Apply patch by @terrichu

Preloaded Member Roles in renders_projects_list and used it in
SearchServicePresenter.

Changelog: performance
---
 app/controllers/concerns/renders_member_access.rb |  3 ++-
 app/controllers/concerns/renders_projects_list.rb |  3 +++
 app/presenters/search_service_presenter.rb        |  3 +++
 ee/spec/requests/search_controller_spec.rb        | 11 +++--------
 spec/requests/search_controller_spec.rb           | 10 +++-------
 5 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/app/controllers/concerns/renders_member_access.rb b/app/controllers/concerns/renders_member_access.rb
index 745830181c1ec..133d797c8ac82 100644
--- a/app/controllers/concerns/renders_member_access.rb
+++ b/app/controllers/concerns/renders_member_access.rb
@@ -15,7 +15,8 @@ def preload_max_member_access_for_collection(klass, collection)
 
     method_name = "max_member_access_for_#{klass.name.underscore}_ids"
 
-    current_user.public_send(method_name, collection.ids) # rubocop:disable GitlabSecurity/PublicSend
+    collection_ids = collection.try(:map, &:id) || collection.ids
+    current_user.public_send(method_name, collection_ids) # rubocop:disable GitlabSecurity/PublicSend
   end
   # rubocop: enable CodeReuse/ActiveRecord
 end
diff --git a/app/controllers/concerns/renders_projects_list.rb b/app/controllers/concerns/renders_projects_list.rb
index 739b2be3fe9e2..2d37bc3f9a56e 100644
--- a/app/controllers/concerns/renders_projects_list.rb
+++ b/app/controllers/concerns/renders_projects_list.rb
@@ -1,8 +1,11 @@
 # frozen_string_literal: true
 
 module RendersProjectsList
+  include RendersMemberAccess
+
   def prepare_projects_for_rendering(projects)
     preload_max_member_access_for_collection(Project, projects)
+    current_user.preloaded_member_roles_for_projects(projects) if current_user
 
     # Call the count methods on every project, so the BatchLoader would load them all at
     # once when the entities are rendered
diff --git a/app/presenters/search_service_presenter.rb b/app/presenters/search_service_presenter.rb
index d7d959217b05e..91e67c379c44b 100644
--- a/app/presenters/search_service_presenter.rb
+++ b/app/presenters/search_service_presenter.rb
@@ -2,6 +2,7 @@
 
 class SearchServicePresenter < Gitlab::View::Presenter::Delegated
   include RendersCommits
+  include RendersProjectsList
 
   presents ::SearchService, as: :search_service
 
@@ -28,6 +29,8 @@ def search_objects
         objects.respond_to?(:eager_load) ? objects.eager_load(:status) : objects # rubocop:disable CodeReuse/ActiveRecord
       when 'commits'
         prepare_commits_for_rendering(objects)
+      when 'projects'
+        prepare_projects_for_rendering(objects)
       else
         objects
       end
diff --git a/ee/spec/requests/search_controller_spec.rb b/ee/spec/requests/search_controller_spec.rb
index ddf147f3ff78a..4497fa26eeb86 100644
--- a/ee/spec/requests/search_controller_spec.rb
+++ b/ee/spec/requests/search_controller_spec.rb
@@ -75,14 +75,9 @@ def send_search_request(params)
         let(:creation_args) { { name: 'foo' } }
         let(:params) { { search: 'foo', scope: 'projects' } }
         # some N+1 queries still exist
-        # each project requires 3 extra queries
-        #   - one count for forks
-        #   - one count for open MRs
-        #   - one count for open Issues
-        # there are 4 additional queries run for the logged in user:
-        # (1) user preferences, (1) user statuses, (1) user details, (1) users
-        # the threshold accounts for 6 projects
-        let(:threshold) { 42 }
+        # 1 for users
+        # 1 for root ancestor for each project
+        let(:threshold) { 7 }
 
         it_behaves_like 'an efficient database result'
       end
diff --git a/spec/requests/search_controller_spec.rb b/spec/requests/search_controller_spec.rb
index 98dda75a2b0d7..f2d4e288ddc30 100644
--- a/spec/requests/search_controller_spec.rb
+++ b/spec/requests/search_controller_spec.rb
@@ -66,13 +66,9 @@ def send_search_request(params)
       let(:creation_args) { { name: 'project' } }
       let(:params) { { search: 'project', scope: 'projects' } }
       # some N+1 queries still exist
-      # each project requires 3 extra queries
-      #   - one count for forks
-      #   - one count for open MRs
-      #   - one count for open Issues
-      # there are 4 additional queries run for the logged in user:
-      # (1) user preferences, (1) user statuses, (1) user details, (1) users
-      let(:threshold) { 17 }
+      # 1 for users
+      # 1 for root ancestor for each project
+      let(:threshold) { 7 }
 
       it_behaves_like 'an efficient database result'
     end
-- 
GitLab