Load repository language from the DB if detected

The repository charts page used to detect the repository language for
each request that was made to the page. Given the detection is an
expensive operation and the same data is stored in the database the
database is now serving the request.

The same goes for an API endpoint that serves the languages.

When a repository is empty or non-existent the languages will always be
empty. And the language detection RPC isn't requested.

Closes: https://gitlab.com/gitlab-org/gitlab-ce/issues/47390
This commit is contained in:
Zeger-Jan van de Weg 2019-02-25 08:57:34 +01:00
parent 48d31abc97
commit abe8cbe90b
5 changed files with 60 additions and 2 deletions

View file

@ -45,7 +45,14 @@ class Projects::GraphsController < Projects::ApplicationController
end
def get_languages
@languages = @project.repository.languages
@languages =
if @project.repository_languages.present?
@project.repository_languages.map do |lang|
{ value: lang.share, label: lang.name, color: lang.color, highlight: lang.color }
end
else
@project.repository.languages
end
end
def fetch_graph

View file

@ -0,0 +1,5 @@
---
title: Load repository language from the database if detected before
merge_request: 25518
author:
type: performance

View file

@ -386,7 +386,11 @@ module API
desc 'Get languages in project repository'
get ':id/languages' do
user_project.repository.languages.map { |language| language.values_at(:label, :value) }.to_h
if user_project.repository_languages.present?
user_project.repository_languages.map { |l| [l.name, l.share] }.to_h
else
user_project.repository.languages.map { |language| language.values_at(:label, :value) }.to_h
end
end
desc 'Remove a project'

View file

@ -24,4 +24,20 @@ describe Projects::GraphsController do
expect(response).to redirect_to action: :charts
end
end
describe 'charts' do
context 'when languages were previously detected' do
let!(:repository_language) { create(:repository_language, project: project) }
it 'sets the languages properly' do
get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' })
expect(assigns[:languages]).to eq(
[value: repository_language.share,
label: repository_language.name,
color: repository_language.color,
highlight: repository_language.color])
end
end
end
end

View file

@ -4,6 +4,15 @@ require 'spec_helper'
shared_examples 'languages and percentages JSON response' do
let(:expected_languages) { project.repository.languages.map { |language| language.values_at(:label, :value)}.to_h }
before do
allow(project.repository).to receive(:languages).and_return(
[{ value: 66.69, label: "Ruby", color: "#701516", highlight: "#701516" },
{ value: 22.98, label: "JavaScript", color: "#f1e05a", highlight: "#f1e05a" },
{ value: 7.91, label: "HTML", color: "#e34c26", highlight: "#e34c26" },
{ value: 2.42, label: "CoffeeScript", color: "#244776", highlight: "#244776" }]
)
end
it 'returns expected language values' do
get api("/projects/#{project.id}/languages", user)
@ -11,6 +20,23 @@ shared_examples 'languages and percentages JSON response' do
expect(json_response).to eq(expected_languages)
expect(json_response.count).to be > 1
end
context 'when the languages were detected before' do
before do
Projects::DetectRepositoryLanguagesService.new(project, project.owner).execute
end
it 'returns the detection from the database' do
# Allow this to happen once, so the expected languages can be determined
expect(project.repository).to receive(:languages).once
get api("/projects/#{project.id}/languages", user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq(expected_languages)
expect(json_response.count).to be > 1
end
end
end
describe API::Projects do