From 88e3ce30ae97ac8eb4b25381cfbe7772819cce0c Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 19 Nov 2017 06:35:25 -0800 Subject: [PATCH] Optimize API /groups/:id/projects by preloading associations Closes #40308 --- changelogs/unreleased/sh-optimize-groups-api.yml | 5 +++++ lib/api/groups.rb | 1 + spec/requests/api/groups_spec.rb | 14 ++++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 changelogs/unreleased/sh-optimize-groups-api.yml diff --git a/changelogs/unreleased/sh-optimize-groups-api.yml b/changelogs/unreleased/sh-optimize-groups-api.yml new file mode 100644 index 00000000000..283c2df5c9f --- /dev/null +++ b/changelogs/unreleased/sh-optimize-groups-api.yml @@ -0,0 +1,5 @@ +--- +title: Optimize API /groups/:id/projects by preloading fork_networks table +merge_request: +author: +type: performance diff --git a/lib/api/groups.rb b/lib/api/groups.rb index bcf2e6dae1d..7e9a5502949 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -172,6 +172,7 @@ module API get ":id/projects" do group = find_group!(params[:id]) projects = GroupProjectsFinder.new(group: group, current_user: current_user, params: project_finder_params).execute + projects = projects.preload(:fork_network, :forked_project_link, :project_feature, :project_group_links, :tags, :taggings, :group, :namespace) projects = reorder_projects(projects) entity = params[:simple] ? Entities::BasicProjectDetails : Entities::Project present paginate(projects), with: entity, current_user: current_user diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 04a658cd6c3..554723d6b1e 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -401,6 +401,20 @@ describe API::Groups do expect(response).to have_gitlab_http_status(404) end + + it 'avoids N+1 queries' do + get api("/groups/#{group1.id}/projects", admin) + + control_count = ActiveRecord::QueryRecorder.new do + get api("/groups/#{group1.id}/projects", admin) + end.count + + create(:project, namespace: group1) + + expect do + get api("/groups/#{group1.id}/projects", admin) + end.not_to exceed_query_limit(control_count) + end end context 'when using group path in URL' do