2019-12-21 20:55:43 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Gitlab
|
|
|
|
module Analytics
|
|
|
|
module CycleAnalytics
|
|
|
|
class RecordsFetcher
|
|
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
include StageQueryHelpers
|
|
|
|
include Gitlab::CycleAnalytics::MetricsTables
|
|
|
|
|
|
|
|
MAX_RECORDS = 20
|
|
|
|
|
|
|
|
MAPPINGS = {
|
|
|
|
Issue => {
|
|
|
|
serializer_class: AnalyticsIssueSerializer,
|
2020-10-24 23:57:45 +05:30
|
|
|
includes_for_query: { project: { namespace: [:route] }, author: [] },
|
2019-12-21 20:55:43 +05:30
|
|
|
columns_for_select: %I[title iid id created_at author_id project_id]
|
|
|
|
},
|
|
|
|
MergeRequest => {
|
|
|
|
serializer_class: AnalyticsMergeRequestSerializer,
|
|
|
|
includes_for_query: { target_project: [:namespace], author: [] },
|
2020-01-01 13:55:28 +05:30
|
|
|
columns_for_select: %I[title iid id created_at author_id state_id target_project_id]
|
2019-12-21 20:55:43 +05:30
|
|
|
}
|
|
|
|
}.freeze
|
|
|
|
|
|
|
|
delegate :subject_class, to: :stage
|
|
|
|
|
|
|
|
def initialize(stage:, query:, params: {})
|
|
|
|
@stage = stage
|
|
|
|
@query = query
|
|
|
|
@params = params
|
2021-04-17 20:07:23 +05:30
|
|
|
@sort = params[:sort] || :end_event
|
|
|
|
@direction = params[:direction] || :desc
|
2021-04-29 21:17:54 +05:30
|
|
|
@page = params[:page] || 1
|
|
|
|
@per_page = MAX_RECORDS
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2019-12-21 20:55:43 +05:30
|
|
|
def serialized_records
|
|
|
|
strong_memoize(:serialized_records) do
|
2021-10-27 15:23:28 +05:30
|
|
|
records = ordered_and_limited_query.select(*columns, *time_columns)
|
|
|
|
|
|
|
|
yield records if block_given?
|
|
|
|
records = preload_associations(records)
|
|
|
|
|
|
|
|
records.map do |record|
|
|
|
|
project = record.project
|
|
|
|
attributes = record.attributes.merge({
|
|
|
|
project_path: project.path,
|
|
|
|
namespace_path: project.namespace.route.path,
|
|
|
|
author: record.author
|
|
|
|
})
|
|
|
|
serializer.represent(attributes)
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-04-29 21:17:54 +05:30
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2019-12-21 20:55:43 +05:30
|
|
|
|
|
|
|
private
|
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
attr_reader :stage, :query, :params, :sort, :direction, :page, :per_page
|
2019-12-21 20:55:43 +05:30
|
|
|
|
|
|
|
def columns
|
|
|
|
MAPPINGS.fetch(subject_class).fetch(:columns_for_select).map do |column_name|
|
|
|
|
subject_class.arel_table[column_name]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def serializer
|
|
|
|
MAPPINGS.fetch(subject_class).fetch(:serializer_class).new
|
|
|
|
end
|
|
|
|
|
|
|
|
def ordered_and_limited_query
|
2021-04-29 21:17:54 +05:30
|
|
|
strong_memoize(:ordered_and_limited_query) do
|
|
|
|
order_by(query, sort, direction, columns).page(page).per(per_page).without_count
|
|
|
|
end
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
|
|
|
def preload_associations(records)
|
2019-12-21 20:55:43 +05:30
|
|
|
# using preloader instead of includes to avoid AR generating a large column list
|
|
|
|
ActiveRecord::Associations::Preloader.new.preload(
|
2021-04-29 21:17:54 +05:30
|
|
|
records,
|
2019-12-21 20:55:43 +05:30
|
|
|
MAPPINGS.fetch(subject_class).fetch(:includes_for_query)
|
|
|
|
)
|
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
records
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
2020-10-24 23:57:45 +05:30
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2020-10-24 23:57:45 +05:30
|
|
|
def time_columns
|
|
|
|
[
|
|
|
|
stage.start_event.timestamp_projection.as('start_event_timestamp'),
|
2021-06-08 01:23:25 +05:30
|
|
|
end_event_timestamp_projection.as('end_event_timestamp'),
|
2020-10-24 23:57:45 +05:30
|
|
|
round_duration_to_seconds.as('total_time')
|
|
|
|
]
|
|
|
|
end
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-12-26 22:10:19 +05:30
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
Gitlab::Analytics::CycleAnalytics::RecordsFetcher.prepend_mod_with('Gitlab::Analytics::CycleAnalytics::RecordsFetcher')
|