Commit 20f78421 authored by Bob Van Landuyt's avatar Bob Van Landuyt

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.
parent 07aaa59b
......@@ -139,8 +139,18 @@ class Namespace < ActiveRecord::Base
def find_fork_of(project)
return nil unless project.fork_network
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?
# User namespace will always default to the global setting
......
---
title: Reduce requests for project forks on show page of projects that have forks
merge_request: 15663
author:
type: performance
......@@ -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
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment