BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
c72abcef
Commit
c72abcef
authored
Jun 01, 2017
by
Yorick Peterse
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fix-n-plus-one-queries-for-user-access' into 'master'
Fix N+1 queries for non-members in comment threads See merge request !11827
parents
358662a9
7f73f440
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
110 additions
and
54 deletions
+110
-54
project_team.rb
app/models/project_team.rb
+8
-1
fix-n-plus-one-queries-for-user-access.yml
...ogs/unreleased/fix-n-plus-one-queries-for-user-access.yml
+4
-0
project_team_spec.rb
spec/models/project_team_spec.rb
+98
-53
No files found.
app/models/project_team.rb
View file @
c72abcef
...
...
@@ -167,7 +167,7 @@ class ProjectTeam
access
=
RequestStore
.
store
[
key
]
end
# Lookup only the IDs we need
# Look
up only the IDs we need
user_ids
=
user_ids
-
access
.
keys
return
access
if
user_ids
.
empty?
...
...
@@ -178,6 +178,13 @@ class ProjectTeam
maximum
(
:access_level
)
access
.
merge!
(
users_access
)
missing_user_ids
=
user_ids
-
users_access
.
keys
missing_user_ids
.
each
do
|
user_id
|
access
[
user_id
]
=
Gitlab
::
Access
::
NO_ACCESS
end
access
end
...
...
changelogs/unreleased/fix-n-plus-one-queries-for-user-access.yml
0 → 100644
View file @
c72abcef
---
title
:
Fix N+1 queries for non-members in comment threads
merge_request
:
author
:
spec/models/project_team_spec.rb
View file @
c72abcef
...
...
@@ -327,69 +327,114 @@ describe ProjectTeam, models: true do
end
end
shared_examples_for
"#max_member_access_for_users"
do
|
enable_request_store
|
describe
"#max_member_access_for_users"
do
shared_examples
'max member access for users'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:group
)
{
create
(
:group
)
}
let
(
:second_group
)
{
create
(
:group
)
}
let
(
:master
)
{
create
(
:user
)
}
let
(
:reporter
)
{
create
(
:user
)
}
let
(
:guest
)
{
create
(
:user
)
}
let
(
:promoted_guest
)
{
create
(
:user
)
}
let
(
:group_developer
)
{
create
(
:user
)
}
let
(
:second_developer
)
{
create
(
:user
)
}
let
(
:user_without_access
)
{
create
(
:user
)
}
let
(
:second_user_without_access
)
{
create
(
:user
)
}
let
(
:users
)
do
[
master
,
reporter
,
promoted_guest
,
guest
,
group_developer
,
second_developer
,
user_without_access
].
map
(
&
:id
)
end
let
(
:expected
)
do
{
master
.
id
=>
Gitlab
::
Access
::
MASTER
,
reporter
.
id
=>
Gitlab
::
Access
::
REPORTER
,
promoted_guest
.
id
=>
Gitlab
::
Access
::
DEVELOPER
,
guest
.
id
=>
Gitlab
::
Access
::
GUEST
,
group_developer
.
id
=>
Gitlab
::
Access
::
DEVELOPER
,
second_developer
.
id
=>
Gitlab
::
Access
::
MASTER
,
user_without_access
.
id
=>
Gitlab
::
Access
::
NO_ACCESS
}
end
before
do
project
.
add_master
(
master
)
project
.
add_reporter
(
reporter
)
project
.
add_guest
(
promoted_guest
)
project
.
add_guest
(
guest
)
project
.
project_group_links
.
create
(
group:
group
,
group_access:
Gitlab
::
Access
::
DEVELOPER
)
group
.
add_master
(
promoted_guest
)
group
.
add_developer
(
group_developer
)
group
.
add_developer
(
second_developer
)
project
.
project_group_links
.
create
(
group:
second_group
,
group_access:
Gitlab
::
Access
::
MASTER
)
second_group
.
add_master
(
second_developer
)
end
it
'returns correct roles for different users'
do
expect
(
project
.
team
.
max_member_access_for_user_ids
(
users
)).
to
eq
(
expected
)
end
end
describe
'#max_member_access_for_user_ids'
do
context
'with RequestStore enabled'
do
before
do
RequestStore
.
begin!
if
enable_request_store
RequestStore
.
begin!
end
after
do
if
enable_request_store
RequestStore
.
end!
RequestStore
.
clear!
end
RequestStore
.
end!
RequestStore
.
clear!
end
it
'returns correct roles for different users'
do
master
=
create
(
:user
)
reporter
=
create
(
:user
)
promoted_guest
=
create
(
:user
)
guest
=
create
(
:user
)
project
=
create
(
:empty_project
)
include_examples
'max member access for users'
project
.
add_master
(
master
)
project
.
add_reporter
(
reporter
)
project
.
add_guest
(
promoted_guest
)
project
.
add_guest
(
guest
)
def
access_levels
(
users
)
project
.
team
.
max_member_access_for_user_ids
(
users
)
end
it
'does not perform extra queries when asked for users who have already been found'
do
access_levels
(
users
)
expect
{
access_levels
(
users
)
}.
not_to
exceed_query_limit
(
0
)
group
=
create
(
:group
)
group_developer
=
create
(
:user
)
second_developer
=
create
(
:user
)
project
.
project_group_links
.
create
(
group:
group
,
group_access:
Gitlab
::
Access
::
DEVELOPER
)
group
.
add_master
(
promoted_guest
)
group
.
add_developer
(
group_developer
)
group
.
add_developer
(
second_developer
)
second_group
=
create
(
:group
)
project
.
project_group_links
.
create
(
group:
second_group
,
group_access:
Gitlab
::
Access
::
MASTER
)
second_group
.
add_master
(
second_developer
)
users
=
[
master
,
reporter
,
promoted_guest
,
guest
,
group_developer
,
second_developer
].
map
(
&
:id
)
expected
=
{
master
.
id
=>
Gitlab
::
Access
::
MASTER
,
reporter
.
id
=>
Gitlab
::
Access
::
REPORTER
,
promoted_guest
.
id
=>
Gitlab
::
Access
::
DEVELOPER
,
guest
.
id
=>
Gitlab
::
Access
::
GUEST
,
group_developer
.
id
=>
Gitlab
::
Access
::
DEVELOPER
,
second_developer
.
id
=>
Gitlab
::
Access
::
MASTER
}
expect
(
project
.
team
.
max_member_access_for_user_ids
(
users
)).
to
eq
(
expected
)
expect
(
access_levels
(
users
)).
to
eq
(
expected
)
end
end
end
describe
'#max_member_access_for_users with RequestStore'
do
it_behaves_like
"#max_member_access_for_users"
,
true
end
it
'only requests the extra users when uncached users are passed'
do
new_user
=
create
(
:user
)
second_new_user
=
create
(
:user
)
all_users
=
users
+
[
new_user
.
id
,
second_new_user
.
id
]
expected_all
=
expected
.
merge
(
new_user
.
id
=>
Gitlab
::
Access
::
NO_ACCESS
,
second_new_user
.
id
=>
Gitlab
::
Access
::
NO_ACCESS
)
access_levels
(
users
)
describe
'#max_member_access_for_users without RequestStore'
do
it_behaves_like
"#max_member_access_for_users"
,
false
queries
=
ActiveRecord
::
QueryRecorder
.
new
{
access_levels
(
all_users
)
}
expect
(
queries
.
count
).
to
eq
(
1
)
expect
(
queries
.
log_message
).
to
match
(
/\W
#{
new_user
.
id
}
\W/
)
expect
(
queries
.
log_message
).
to
match
(
/\W
#{
second_new_user
.
id
}
\W/
)
expect
(
queries
.
log_message
).
not_to
match
(
/\W
#{
promoted_guest
.
id
}
\W/
)
expect
(
access_levels
(
all_users
)).
to
eq
(
expected_all
)
end
end
context
'with RequestStore disabled'
do
include_examples
'max member access for users'
end
end
end
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