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/models/event_collection.rb')
-rw-r--r--app/models/event_collection.rb43
1 files changed, 23 insertions, 20 deletions
diff --git a/app/models/event_collection.rb b/app/models/event_collection.rb
index a4c69b11781..4778f74568e 100644
--- a/app/models/event_collection.rb
+++ b/app/models/event_collection.rb
@@ -6,6 +6,8 @@
# in a controller), it's not suitable for building queries that are used for
# building other queries.
class EventCollection
+ include Gitlab::Utils::StrongMemoize
+
# To prevent users from putting too much pressure on the database by cycling
# through thousands of events we put a limit on the number of pages.
MAX_PAGE = 10
@@ -13,57 +15,52 @@ class EventCollection
# projects - An ActiveRecord::Relation object that returns the projects for
# which to retrieve events.
# filter - An EventFilter instance to use for filtering events.
- def initialize(projects, limit: 20, offset: 0, filter: nil)
+ def initialize(projects, limit: 20, offset: 0, filter: nil, groups: nil)
@projects = projects
@limit = limit
@offset = offset
@filter = filter
+ @groups = groups
end
# Returns an Array containing the events.
def to_a
return [] if current_page > MAX_PAGE
- relation = if Gitlab::Database.join_lateral_supported?
- relation_with_join_lateral
+ relation = if groups
+ project_and_group_events
else
- relation_without_join_lateral
+ relation_with_join_lateral('project_id', projects)
end
+ relation = paginate_events(relation)
relation.with_associations.to_a
end
private
- # Returns the events relation to use when JOIN LATERAL is not supported.
- #
- # This relation simply gets all the events for all authorized projects, then
- # limits that set.
- def relation_without_join_lateral
- events = filtered_events.in_projects(projects)
+ def project_and_group_events
+ project_events = relation_with_join_lateral('project_id', projects)
+ group_events = relation_with_join_lateral('group_id', groups)
- paginate_events(events)
+ Event.from_union([project_events, group_events]).recent
end
- # Returns the events relation to use when JOIN LATERAL is supported.
- #
# This relation is built using JOIN LATERAL, producing faster queries than a
# regular LIMIT + OFFSET approach.
- def relation_with_join_lateral
- projects_for_lateral = projects.select(:id).to_sql
+ def relation_with_join_lateral(parent_column, parents)
+ parents_for_lateral = parents.select(:id).to_sql
lateral = filtered_events
.limit(limit_for_join_lateral)
- .where('events.project_id = projects_for_lateral.id')
+ .where("events.#{parent_column} = parents_for_lateral.id") # rubocop:disable GitlabSecurity/SqlInjection
.to_sql
# The outer query does not need to re-apply the filters since the JOIN
# LATERAL body already takes care of this.
- outer = base_relation
- .from("(#{projects_for_lateral}) projects_for_lateral")
+ base_relation
+ .from("(#{parents_for_lateral}) parents_for_lateral")
.joins("JOIN LATERAL (#{lateral}) AS #{Event.table_name} ON true")
-
- paginate_events(outer)
end
def filtered_events
@@ -97,4 +94,10 @@ class EventCollection
def projects
@projects.except(:order)
end
+
+ def groups
+ strong_memoize(:groups) do
+ groups.except(:order) if @groups
+ end
+ end
end