Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Jérome Perrin
gitlab-ce
Commits
26d3da4b
Commit
26d3da4b
authored
Mar 13, 2017
by
Tiago Botelho
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removes n+1 query from tags and branches indexes
parent
ce5d1b6f
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
56 additions
and
6 deletions
+56
-6
app/controllers/projects/branches_controller.rb
app/controllers/projects/branches_controller.rb
+8
-2
app/controllers/projects/tags_controller.rb
app/controllers/projects/tags_controller.rb
+3
-1
app/models/ci/pipeline.rb
app/models/ci/pipeline.rb
+6
-0
app/views/projects/branches/_branch.html.haml
app/views/projects/branches/_branch.html.haml
+1
-1
app/views/projects/buttons/_download.html.haml
app/views/projects/buttons/_download.html.haml
+2
-1
app/views/projects/tags/_tag.html.haml
app/views/projects/tags/_tag.html.haml
+1
-1
changelogs/unreleased/fix-slow-queries-for-branches-index.yml
...gelogs/unreleased/fix-slow-queries-for-branches-index.yml
+4
-0
spec/features/projects/branches_spec.rb
spec/features/projects/branches_spec.rb
+8
-0
spec/features/tags/master_views_tags_spec.rb
spec/features/tags/master_views_tags_spec.rb
+10
-0
spec/models/ci/pipeline_spec.rb
spec/models/ci/pipeline_spec.rb
+13
-0
No files found.
app/controllers/projects/branches_controller.rb
View file @
26d3da4b
...
@@ -11,16 +11,18 @@ class Projects::BranchesController < Projects::ApplicationController
...
@@ -11,16 +11,18 @@ class Projects::BranchesController < Projects::ApplicationController
@sort
=
params
[
:sort
].
presence
||
sort_value_name
@sort
=
params
[
:sort
].
presence
||
sort_value_name
@branches
=
BranchesFinder
.
new
(
@repository
,
params
).
execute
@branches
=
BranchesFinder
.
new
(
@repository
,
params
).
execute
@branches
=
Kaminari
.
paginate_array
(
@branches
).
page
(
params
[
:page
])
unless
params
[
:show_all
].
present?
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
do
format
.
html
do
paginate_branches
@refs_pipelines
=
@project
.
pipelines
.
latest_successful_for_refs
(
@branches
.
map
(
&
:name
))
@max_commits
=
@branches
.
reduce
(
0
)
do
|
memo
,
branch
|
@max_commits
=
@branches
.
reduce
(
0
)
do
|
memo
,
branch
|
diverging_commit_counts
=
repository
.
diverging_commit_counts
(
branch
)
diverging_commit_counts
=
repository
.
diverging_commit_counts
(
branch
)
[
memo
,
diverging_commit_counts
[
:behind
],
diverging_commit_counts
[
:ahead
]].
max
[
memo
,
diverging_commit_counts
[
:behind
],
diverging_commit_counts
[
:ahead
]].
max
end
end
end
end
format
.
json
do
format
.
json
do
paginate_branches
unless
params
[
:show_all
]
render
json:
@branches
.
map
(
&
:name
)
render
json:
@branches
.
map
(
&
:name
)
end
end
end
end
...
@@ -91,6 +93,10 @@ class Projects::BranchesController < Projects::ApplicationController
...
@@ -91,6 +93,10 @@ class Projects::BranchesController < Projects::ApplicationController
end
end
end
end
def
paginate_branches
@branches
=
Kaminari
.
paginate_array
(
@branches
).
page
(
params
[
:page
])
end
def
url_to_autodeploy_setup
(
project
,
branch_name
)
def
url_to_autodeploy_setup
(
project
,
branch_name
)
namespace_project_new_blob_path
(
namespace_project_new_blob_path
(
project
.
namespace
,
project
.
namespace
,
...
...
app/controllers/projects/tags_controller.rb
View file @
26d3da4b
...
@@ -14,7 +14,9 @@ class Projects::TagsController < Projects::ApplicationController
...
@@ -14,7 +14,9 @@ class Projects::TagsController < Projects::ApplicationController
@tags
=
TagsFinder
.
new
(
@repository
,
params
).
execute
@tags
=
TagsFinder
.
new
(
@repository
,
params
).
execute
@tags
=
Kaminari
.
paginate_array
(
@tags
).
page
(
params
[
:page
])
@tags
=
Kaminari
.
paginate_array
(
@tags
).
page
(
params
[
:page
])
@releases
=
project
.
releases
.
where
(
tag:
@tags
.
map
(
&
:name
))
tag_names
=
@tags
.
map
(
&
:name
)
@tags_pipelines
=
@project
.
pipelines
.
latest_successful_for_refs
(
tag_names
)
@releases
=
project
.
releases
.
where
(
tag:
tag_names
)
end
end
def
show
def
show
...
...
app/models/ci/pipeline.rb
View file @
26d3da4b
...
@@ -115,6 +115,12 @@ module Ci
...
@@ -115,6 +115,12 @@ module Ci
success
.
latest
(
ref
).
order
(
id: :desc
).
first
success
.
latest
(
ref
).
order
(
id: :desc
).
first
end
end
def
self
.
latest_successful_for_refs
(
refs
)
success
.
latest
(
refs
).
order
(
id: :desc
).
each_with_object
({})
do
|
pipeline
,
hash
|
hash
[
pipeline
.
ref
]
||=
pipeline
end
end
def
self
.
truncate_sha
(
sha
)
def
self
.
truncate_sha
(
sha
)
sha
[
0
...
8
]
sha
[
0
...
8
]
end
end
...
...
app/views/projects/branches/_branch.html.haml
View file @
26d3da4b
...
@@ -27,7 +27,7 @@
...
@@ -27,7 +27,7 @@
=
link_to
namespace_project_compare_index_path
(
@project
.
namespace
,
@project
,
from:
@repository
.
root_ref
,
to:
branch
.
name
),
class:
"btn btn-default
#{
'prepend-left-10'
unless
merge_project
}
"
,
method: :post
,
title:
"Compare"
do
=
link_to
namespace_project_compare_index_path
(
@project
.
namespace
,
@project
,
from:
@repository
.
root_ref
,
to:
branch
.
name
),
class:
"btn btn-default
#{
'prepend-left-10'
unless
merge_project
}
"
,
method: :post
,
title:
"Compare"
do
Compare
Compare
=
render
'projects/buttons/download'
,
project:
@project
,
ref:
branch
.
name
=
render
'projects/buttons/download'
,
project:
@project
,
ref:
branch
.
name
,
pipeline:
@refs_pipelines
[
branch
.
name
]
-
if
can?
(
current_user
,
:push_code
,
@project
)
-
if
can?
(
current_user
,
:push_code
,
@project
)
=
link_to
namespace_project_branch_path
(
@project
.
namespace
,
@project
,
branch
.
name
),
=
link_to
namespace_project_branch_path
(
@project
.
namespace
,
@project
,
branch
.
name
),
...
...
app/views/projects/buttons/_download.html.haml
View file @
26d3da4b
-
pipeline
=
local_assigns
.
fetch
(
:pipeline
)
{
project
.
pipelines
.
latest_successful_for
(
ref
)
}
-
if
!
project
.
empty_repo?
&&
can?
(
current_user
,
:download_code
,
project
)
-
if
!
project
.
empty_repo?
&&
can?
(
current_user
,
:download_code
,
project
)
.project-action-button.dropdown.inline
>
.project-action-button.dropdown.inline
>
%button
.btn
{
'data-toggle'
=>
'dropdown'
}
%button
.btn
{
'data-toggle'
=>
'dropdown'
}
...
@@ -24,7 +26,6 @@
...
@@ -24,7 +26,6 @@
%i
.fa.fa-download
%i
.fa.fa-download
%span
Download tar
%span
Download tar
-
pipeline
=
project
.
pipelines
.
latest_successful_for
(
ref
)
-
if
pipeline
-
if
pipeline
-
artifacts
=
pipeline
.
builds
.
latest
.
with_artifacts
-
artifacts
=
pipeline
.
builds
.
latest
.
with_artifacts
-
if
artifacts
.
any?
-
if
artifacts
.
any?
...
...
app/views/projects/tags/_tag.html.haml
View file @
26d3da4b
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
=
markdown_field
(
release
,
:description
)
=
markdown_field
(
release
,
:description
)
.row-fixed-content.controls
.row-fixed-content.controls
=
render
'projects/buttons/download'
,
project:
@project
,
ref:
tag
.
name
=
render
'projects/buttons/download'
,
project:
@project
,
ref:
tag
.
name
,
pipeline:
@tags_pipelines
[
tag
.
name
]
-
if
can?
(
current_user
,
:push_code
,
@project
)
-
if
can?
(
current_user
,
:push_code
,
@project
)
=
link_to
edit_namespace_project_tag_release_path
(
@project
.
namespace
,
@project
,
tag
.
name
),
class:
'btn has-tooltip'
,
title:
"Edit release notes"
,
data:
{
container:
"body"
}
do
=
link_to
edit_namespace_project_tag_release_path
(
@project
.
namespace
,
@project
,
tag
.
name
),
class:
'btn has-tooltip'
,
title:
"Edit release notes"
,
data:
{
container:
"body"
}
do
...
...
changelogs/unreleased/fix-slow-queries-for-branches-index.yml
0 → 100644
View file @
26d3da4b
---
title
:
Fixes n+1 query for tags and branches index page
merge_request
:
9905
author
:
spec/features/projects/branches_spec.rb
View file @
26d3da4b
...
@@ -17,6 +17,14 @@ describe 'Branches', feature: true do
...
@@ -17,6 +17,14 @@ describe 'Branches', feature: true do
repository
.
branches
{
|
branch
|
expect
(
page
).
to
have_content
(
"
#{
branch
.
name
}
"
)
}
repository
.
branches
{
|
branch
|
expect
(
page
).
to
have_content
(
"
#{
branch
.
name
}
"
)
}
expect
(
page
).
to
have_content
(
"Protected branches can be managed in project settings"
)
expect
(
page
).
to
have_content
(
"Protected branches can be managed in project settings"
)
end
end
it
'avoids a N+1 query in branches index'
do
control_count
=
ActiveRecord
::
QueryRecorder
.
new
{
visit
namespace_project_branches_path
(
project
.
namespace
,
project
)
}.
count
%w(one two three four five)
.
each
{
|
ref
|
repository
.
add_branch
(
@user
,
ref
,
'master'
)
}
expect
{
visit
namespace_project_branches_path
(
project
.
namespace
,
project
)
}.
not_to
exceed_query_limit
(
control_count
)
end
end
end
describe
'Find branches'
do
describe
'Find branches'
do
...
...
spec/features/tags/master_views_tags_spec.rb
View file @
26d3da4b
...
@@ -27,10 +27,20 @@ feature 'Master views tags', feature: true do
...
@@ -27,10 +27,20 @@ feature 'Master views tags', feature: true do
context
'when project has tags'
do
context
'when project has tags'
do
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
let
(
:repository
)
{
project
.
repository
}
before
do
before
do
visit
namespace_project_tags_path
(
project
.
namespace
,
project
)
visit
namespace_project_tags_path
(
project
.
namespace
,
project
)
end
end
scenario
'avoids a N+1 query in branches index'
do
control_count
=
ActiveRecord
::
QueryRecorder
.
new
{
visit
namespace_project_tags_path
(
project
.
namespace
,
project
)
}.
count
%w(one two three four five)
.
each
{
|
tag
|
repository
.
add_tag
(
user
,
tag
,
'master'
,
'foo'
)
}
expect
{
visit
namespace_project_tags_path
(
project
.
namespace
,
project
)
}.
not_to
exceed_query_limit
(
control_count
)
end
scenario
'views the tags list page'
do
scenario
'views the tags list page'
do
expect
(
page
).
to
have_content
'v1.0.0'
expect
(
page
).
to
have_content
'v1.0.0'
end
end
...
...
spec/models/ci/pipeline_spec.rb
View file @
26d3da4b
...
@@ -532,6 +532,19 @@ describe Ci::Pipeline, models: true do
...
@@ -532,6 +532,19 @@ describe Ci::Pipeline, models: true do
end
end
end
end
describe
'.latest_successful_for_refs'
do
include_context
'with some outdated pipelines'
let!
(
:latest_successful_pipeline1
)
{
create_pipeline
(
:success
,
'ref1'
,
'D'
)
}
let!
(
:latest_successful_pipeline2
)
{
create_pipeline
(
:success
,
'ref2'
,
'D'
)
}
it
'returns the latest successful pipeline for both refs'
do
refs
=
%w(ref1 ref2 ref3)
expect
(
described_class
.
latest_successful_for_refs
(
refs
)).
to
eq
({
'ref1'
=>
latest_successful_pipeline1
,
'ref2'
=>
latest_successful_pipeline2
})
end
end
describe
'#status'
do
describe
'#status'
do
let
(
:build
)
do
let
(
:build
)
do
create
(
:ci_build
,
:created
,
pipeline:
pipeline
,
name:
'test'
)
create
(
:ci_build
,
:created
,
pipeline:
pipeline
,
name:
'test'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment