Skip to content
代码片段 群组 项目
未验证 提交 0891567c 编辑于 作者: Allison Browne's avatar Allison Browne 提交者: GitLab
浏览文件

Merge branch 'preload-downstream-pipeline-for-commit-statuses' into 'master'

Preload downstream_pipeline in CommitStatusPreloader

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142199



Merged-by: default avatarAllison Browne <abrowne@gitlab.com>
Approved-by: default avatarAllison Browne <abrowne@gitlab.com>
Reviewed-by: default avatarAllison Browne <abrowne@gitlab.com>
Reviewed-by: default avatarMax Fan <mfan@gitlab.com>
Co-authored-by: default avatarHordur Freyr Yngvason <hfyngvason@gitlab.com>
No related branches found
No related tags found
无相关合并请求
...@@ -24,7 +24,24 @@ def objects(klass) ...@@ -24,7 +24,24 @@ def objects(klass)
end end
def associations(klass, relations) def associations(klass, relations)
klass.reflections.keys.map(&:to_sym) & relations.map(&:to_sym) klass_reflections = klass.reflections.keys.map(&:to_sym).to_set
result = []
relations.each do |entry|
if entry.respond_to?(:to_sym)
result << entry.to_sym if klass_reflections.include?(entry.to_sym)
elsif entry.is_a?(Hash)
entry = entry.select do |key, _value|
klass_reflections.include?(key.to_sym)
end
result << entry if entry.present?
else
raise ArgumentError, "Invalid relation: #{entry.inspect}"
end
end
result
end end
end end
end end
...@@ -10,14 +10,14 @@ class StageEntity < Grape::Entity ...@@ -10,14 +10,14 @@ class StageEntity < Grape::Entity
end end
expose :groups, expose :groups,
if: -> (_, opts) { opts[:grouped] }, if: ->(_, opts) { opts[:grouped] },
with: JobGroupEntity with: JobGroupEntity
expose :latest_statuses, if: -> (_, opts) { opts[:details] }, with: Ci::JobEntity do |stage| expose :latest_statuses, if: ->(_, opts) { opts[:details] }, with: Ci::JobEntity do |_stage|
latest_statuses latest_statuses
end end
expose :retried, if: -> (_, opts) { opts[:retried] }, with: Ci::JobEntity do |stage| expose :retried, if: ->(_, opts) { opts[:retried] }, with: Ci::JobEntity do |_stage|
retried_statuses retried_statuses
end end
...@@ -67,7 +67,12 @@ def grouped_retried_statuses ...@@ -67,7 +67,12 @@ def grouped_retried_statuses
end end
def preload_metadata(statuses) def preload_metadata(statuses)
Preloaders::CommitStatusPreloader.new(statuses).execute([:metadata, :pipeline]) relations = [:metadata, :pipeline]
if Feature.enabled?(:preload_ci_bridge_downstream_pipelines, stage.pipeline.project, type: :gitlab_com_derisk)
relations << { downstream_pipeline: [:user, { project: [:route, { namespace: :route }] }] }
end
Preloaders::CommitStatusPreloader.new(statuses).execute(relations)
statuses statuses
end end
......
---
name: preload_ci_bridge_downstream_pipelines
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142199
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17473
milestone: '16.9'
group: 'group::pipeline execution'
type: gitlab_com_derisk
default_enabled: false
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
let_it_be(:generic_commit_status2) { create(:generic_commit_status, pipeline: pipeline) } let_it_be(:generic_commit_status2) { create(:generic_commit_status, pipeline: pipeline) }
describe '#execute' do describe '#execute' do
let(:relations) { %i[pipeline metadata tags job_artifacts_archive downstream_pipeline] } let(:relations) { %i[pipeline metadata tags job_artifacts_archive { downstream_pipeline: [:user] }] }
let(:statuses) { CommitStatus.where(commit_id: pipeline.id).all } let(:statuses) { CommitStatus.where(commit_id: pipeline.id).all }
subject(:execute) { described_class.new(statuses).execute(relations) } subject(:execute) { described_class.new(statuses).execute(relations) }
...@@ -30,6 +30,12 @@ ...@@ -30,6 +30,12 @@
end.to issue_same_number_of_queries_as(control) end.to issue_same_number_of_queries_as(control)
end end
context 'when given an invalid relation' do
let(:relations) { [1] }
it { expect { execute }.to raise_error(ArgumentError, "Invalid relation: 1") }
end
private private
def call_each_relation(statuses) def call_each_relation(statuses)
......
...@@ -96,5 +96,35 @@ ...@@ -96,5 +96,35 @@
expect(subject[:status][:action]).to be_present expect(subject[:status][:action]).to be_present
end end
end end
context 'when details: true' do
def serialize(stage)
described_class.new(stage, request: request, details: true).as_json
end
it 'avoids N+1 queries on latest_statuses', :use_sql_query_cache, :request_store do
pipeline = create(:ci_pipeline)
stage = create(:ci_stage, pipeline: pipeline, status: :success)
serialize(stage) # Warm up O(1) queries
# Prepare control
create(:ci_build, :tags, ci_stage: stage, pipeline: pipeline)
create(:ci_bridge, ci_stage: stage, pipeline: pipeline)
create(:generic_commit_status, ci_stage: stage, pipeline: pipeline)
control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
serialize(stage)
end
# Prepare sample using a generous number to counteract any caches from
# the control
create_list(:ci_build, 10, :tags, ci_stage: stage, pipeline: pipeline)
create_list(:ci_bridge, 10, ci_stage: stage, pipeline: pipeline)
create_list(:generic_commit_status, 10, ci_stage: stage, pipeline: pipeline)
expect { serialize(stage) }.not_to exceed_query_limit(control)
end
end
end end
end end
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册