diff options
author | Bob Van Landuyt <bob@vanlanduyt.co> | 2017-11-30 14:26:08 +0100 |
---|---|---|
committer | Bob Van Landuyt <bob@vanlanduyt.co> | 2017-12-04 17:43:48 +0100 |
commit | 20f78421c82d626a3b43924146b7878fe4777ae8 (patch) | |
tree | b24c602574cb20c907a1ac228c8b00c104cbc836 | |
parent | 07aaa59b1c28bc7be9fdd98c9334522f60306723 (diff) | |
download | gitlab-ce-20f78421c82d626a3b43924146b7878fe4777ae8.tar.gz |
Cache the forks in a namespace in the RequestStore
On the `show` of a project that is part of a fork network. We check if
the user already created a fork of this project in their personal
namespace.
We do this in several places, so caching the result of this query in
the request store prevents us from repeating it.
-rw-r--r-- | app/models/namespace.rb | 12 | ||||
-rw-r--r-- | changelogs/unreleased/bvl-limit-fork-queries-on-project-show.yml | 5 | ||||
-rw-r--r-- | spec/controllers/projects_controller_spec.rb | 23 | ||||
-rw-r--r-- | spec/models/namespace_spec.rb | 10 |
4 files changed, 48 insertions, 2 deletions
diff --git a/app/models/namespace.rb b/app/models/namespace.rb index fa76729a702..901dbf2ba69 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -139,7 +139,17 @@ class Namespace < ActiveRecord::Base def find_fork_of(project) return nil unless project.fork_network - project.fork_network.find_forks_in(projects).first + if RequestStore.active? + forks_in_namespace = RequestStore.fetch("namespaces:#{id}:forked_projects") do + Hash.new do |found_forks, project| + found_forks[project] = project.fork_network.find_forks_in(projects).first + end + end + + forks_in_namespace[project] + else + project.fork_network.find_forks_in(projects).first + end end def lfs_enabled? diff --git a/changelogs/unreleased/bvl-limit-fork-queries-on-project-show.yml b/changelogs/unreleased/bvl-limit-fork-queries-on-project-show.yml new file mode 100644 index 00000000000..299d9bf6b9c --- /dev/null +++ b/changelogs/unreleased/bvl-limit-fork-queries-on-project-show.yml @@ -0,0 +1,5 @@ +--- +title: Reduce requests for project forks on show page of projects that have forks +merge_request: 15663 +author: +type: performance diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index e7ab714c550..39ee5e8691b 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -261,6 +261,29 @@ describe ProjectsController do expect(response).to redirect_to(namespace_project_path) end end + + context 'when the project is forked and has a repository', :request_store do + let(:public_project) { create(:project, :public, :repository) } + + render_views + + before do + # View the project as a user that does not have any rights + sign_in(create(:user)) + + fork_project(public_project) + end + + it 'does not increase the number of queries when the project is forked' do + # When a project is part of a fork network, we check if the `current_user` + # has a fork in their own namespace. We query this several times. Caching + # the result in the RequestStore brings the number of queries for this + # request down from 64 to 59. + + expect { get(:show, namespace_id: public_project.namespace, id: public_project) } + .not_to exceed_query_limit(59) + end + end end describe "#update" do diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 90b768f595e..3817f20bfe7 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -531,7 +531,7 @@ describe Namespace do end end - describe '#has_forks_of?' do + describe '#find_fork_of?' do let(:project) { create(:project, :public) } let!(:forked_project) { fork_project(project, namespace.owner, namespace: namespace) } @@ -550,5 +550,13 @@ describe Namespace do expect(other_namespace.find_fork_of(project)).to eq(other_fork) end + + context 'with request store enabled', :request_store do + it 'only queries once' do + expect(project.fork_network).to receive(:find_forks_in).once.and_call_original + + 2.times { namespace.find_fork_of(project) } + end + end end end |