Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/finders/autocomplete/users_finder.rb')
-rw-r--r--app/finders/autocomplete/users_finder.rb50
1 files changed, 40 insertions, 10 deletions
diff --git a/app/finders/autocomplete/users_finder.rb b/app/finders/autocomplete/users_finder.rb
index e7a24cde2bd..ddd68524a04 100644
--- a/app/finders/autocomplete/users_finder.rb
+++ b/app/finders/autocomplete/users_finder.rb
@@ -9,6 +9,7 @@ module Autocomplete
# consistent and removes the need for implementing keyset pagination to
# ensure good performance.
LIMIT = 20
+ BATCH_SIZE = 1000
attr_reader :current_user, :project, :group, :search,
:author_id, :todo_filter, :todo_state_filter,
@@ -62,7 +63,19 @@ module Autocomplete
# When changing the order of these method calls, make sure that
# reorder_by_name() is called _before_ optionally_search(), otherwise
# reorder_by_name will break the ORDER BY applied in optionally_search().
- find_users
+ if project
+ project.authorized_users.union_with_user(author_id).merge(users_relation)
+ elsif group
+ find_group_users(group)
+ elsif current_user
+ users_relation
+ else
+ User.none
+ end.to_a
+ end
+
+ def users_relation
+ User
.where(state: states)
.non_internal
.reorder_by_name
@@ -73,7 +86,6 @@ module Autocomplete
todo_state: todo_state_filter
)
.limit(LIMIT)
- .to_a
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -85,15 +97,33 @@ module Autocomplete
author_id.present? && current_user
end
- def find_users
- if project
- project.authorized_users.union_with_user(author_id)
- elsif group
- ::Autocomplete::GroupUsersFinder.new(group: group).execute # rubocop: disable CodeReuse/Finder
- elsif current_user
- User.all
+ def find_group_users(group)
+ if Feature.enabled?(:group_users_autocomplete_using_batch_reduction, current_user)
+ members_relation = ::Autocomplete::GroupUsersFinder.new(group: group, members_relation: true).execute # rubocop: disable CodeReuse/Finder
+
+ user_ids = Set.new
+ members_relation.each_batch(of: BATCH_SIZE) do |relation|
+ user_ids += relation.pluck_user_ids
+ end
+
+ user_relations = []
+ user_ids.to_a.in_groups_of(BATCH_SIZE, false) do |batch_user_ids|
+ user_relations << users_relation.id_in(batch_user_ids)
+ end
+
+ # When there is more than 1 batch, we need to apply users_relation again on
+ # the top results per-batch so that we return results in the correct order.
+ if user_relations.empty?
+ User.none
+ elsif user_relations.one?
+ user_relations.first
+ else
+ # We pluck the ids per batch so that we don't send an unbounded number of ids in one query
+ user_ids = user_relations.flat_map(&:pluck_primary_key)
+ users_relation.id_in(user_ids)
+ end
else
- User.none
+ ::Autocomplete::GroupUsersFinder.new(group: group).execute.merge(users_relation) # rubocop: disable CodeReuse/Finder
end
end