Speed up Group#user_ids_for_project_authorizations
This commit is contained in:
parent
455dc74e65
commit
d7b03c37f8
|
@ -11,11 +11,11 @@ module Emails
|
|||
@member_source_type = member_source_type
|
||||
@member_id = member_id
|
||||
|
||||
admins = member_source.members.owners_and_masters.includes(:user).pluck(:notification_email)
|
||||
admins = member_source.members.owners_and_masters.pluck(:notification_email)
|
||||
# A project in a group can have no explicit owners/masters, in that case
|
||||
# we fallbacks to the group's owners/masters.
|
||||
if admins.empty? && member_source.respond_to?(:group) && member_source.group
|
||||
admins = member_source.group.members.owners_and_masters.includes(:user).pluck(:notification_email)
|
||||
admins = member_source.group.members.owners_and_masters.pluck(:notification_email)
|
||||
end
|
||||
|
||||
mail(to: admins,
|
||||
|
|
|
@ -212,21 +212,39 @@ class Group < Namespace
|
|||
end
|
||||
|
||||
def user_ids_for_project_authorizations
|
||||
users_with_parents.pluck(:id)
|
||||
members_with_parents.pluck(:user_id)
|
||||
end
|
||||
|
||||
def members_with_parents
|
||||
GroupMember.active.where(source_id: ancestors.pluck(:id).push(id)).where.not(user_id: nil)
|
||||
# Avoids an unnecessary SELECT when the group has no parents
|
||||
source_ids =
|
||||
if parent_id
|
||||
self_and_ancestors.reorder(nil).select(:id)
|
||||
else
|
||||
id
|
||||
end
|
||||
|
||||
GroupMember
|
||||
.active_without_invites
|
||||
.where(source_id: source_ids)
|
||||
end
|
||||
|
||||
def members_with_descendants
|
||||
GroupMember
|
||||
.active_without_invites
|
||||
.where(source_id: self_and_descendants.reorder(nil).select(:id))
|
||||
end
|
||||
|
||||
def users_with_parents
|
||||
User.where(id: members_with_parents.select(:user_id))
|
||||
User
|
||||
.where(id: members_with_parents.select(:user_id))
|
||||
.reorder(nil)
|
||||
end
|
||||
|
||||
def users_with_descendants
|
||||
members_with_descendants = GroupMember.non_request.where(source_id: descendants.pluck(:id).push(id))
|
||||
|
||||
User.where(id: members_with_descendants.select(:user_id))
|
||||
User
|
||||
.where(id: members_with_descendants.select(:user_id))
|
||||
.reorder(nil)
|
||||
end
|
||||
|
||||
def max_member_access_for_user(user)
|
||||
|
|
|
@ -41,9 +41,20 @@ class Member < ActiveRecord::Base
|
|||
is_external_invite = arel_table[:user_id].eq(nil).and(arel_table[:invite_token].not_eq(nil))
|
||||
user_is_active = User.arel_table[:state].eq(:active)
|
||||
|
||||
includes(:user).references(:users)
|
||||
.where(is_external_invite.or(user_is_active))
|
||||
user_ok = Arel::Nodes::Grouping.new(is_external_invite).or(user_is_active)
|
||||
|
||||
left_join_users
|
||||
.where(user_ok)
|
||||
.where(requested_at: nil)
|
||||
.reorder(nil)
|
||||
end
|
||||
|
||||
# Like active, but without invites. For when a User is required.
|
||||
scope :active_without_invites, -> do
|
||||
left_join_users
|
||||
.where(users: { state: 'active' })
|
||||
.where(requested_at: nil)
|
||||
.reorder(nil)
|
||||
end
|
||||
|
||||
scope :invite, -> { where.not(invite_token: nil) }
|
||||
|
|
|
@ -156,6 +156,14 @@ class Namespace < ActiveRecord::Base
|
|||
.base_and_ancestors
|
||||
end
|
||||
|
||||
def self_and_ancestors
|
||||
return self.class.where(id: id) unless parent_id
|
||||
|
||||
Gitlab::GroupHierarchy
|
||||
.new(self.class.where(id: id))
|
||||
.base_and_ancestors
|
||||
end
|
||||
|
||||
# Returns all the descendants of the current namespace.
|
||||
def descendants
|
||||
Gitlab::GroupHierarchy
|
||||
|
@ -163,6 +171,12 @@ class Namespace < ActiveRecord::Base
|
|||
.base_and_descendants
|
||||
end
|
||||
|
||||
def self_and_descendants
|
||||
Gitlab::GroupHierarchy
|
||||
.new(self.class.where(id: id))
|
||||
.base_and_descendants
|
||||
end
|
||||
|
||||
def user_ids_for_project_authorizations
|
||||
[owner_id]
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix timeouts when creating projects in groups with many members
|
||||
merge_request: 13508
|
||||
author:
|
||||
type: fixed
|
|
@ -315,6 +315,20 @@ describe Namespace do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#self_and_ancestors', :nested_groups do
|
||||
let(:group) { create(:group) }
|
||||
let(:nested_group) { create(:group, parent: group) }
|
||||
let(:deep_nested_group) { create(:group, parent: nested_group) }
|
||||
let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
|
||||
|
||||
it 'returns the correct ancestors' do
|
||||
expect(very_deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
|
||||
expect(deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group)
|
||||
expect(nested_group.self_and_ancestors).to contain_exactly(group, nested_group)
|
||||
expect(group.self_and_ancestors).to contain_exactly(group)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#descendants', :nested_groups do
|
||||
let!(:group) { create(:group, path: 'git_lab') }
|
||||
let!(:nested_group) { create(:group, parent: group) }
|
||||
|
@ -331,6 +345,22 @@ describe Namespace do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#self_and_descendants', :nested_groups do
|
||||
let!(:group) { create(:group, path: 'git_lab') }
|
||||
let!(:nested_group) { create(:group, parent: group) }
|
||||
let!(:deep_nested_group) { create(:group, parent: nested_group) }
|
||||
let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
|
||||
let!(:another_group) { create(:group, path: 'gitllab') }
|
||||
let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
|
||||
|
||||
it 'returns the correct descendants' do
|
||||
expect(very_deep_nested_group.self_and_descendants).to contain_exactly(very_deep_nested_group)
|
||||
expect(deep_nested_group.self_and_descendants).to contain_exactly(deep_nested_group, very_deep_nested_group)
|
||||
expect(nested_group.self_and_descendants).to contain_exactly(nested_group, deep_nested_group, very_deep_nested_group)
|
||||
expect(group.self_and_descendants).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#users_with_descendants', :nested_groups do
|
||||
let(:user_a) { create(:user) }
|
||||
let(:user_b) { create(:user) }
|
||||
|
|
Loading…
Reference in New Issue