Commit cbfba1ee authored by Matthias Käppler's avatar Matthias Käppler Committed by Arturo Herrero

Batch-load environments in EE pipelines

This fixes an N+1 when rendering the pipeline tab.
parent f7648c58
...@@ -73,7 +73,14 @@ module Ci ...@@ -73,7 +73,14 @@ module Ci
return unless has_environment? return unless has_environment?
strong_memoize(:persisted_environment) do strong_memoize(:persisted_environment) do
Environment.find_by(name: expanded_environment_name, project: project) # This code path has caused N+1s in the past, since environments are only indirectly
# associated to builds and pipelines; see https://gitlab.com/gitlab-org/gitlab/-/issues/326445
# We therefore batch-load them to prevent dormant N+1s until we found a proper solution.
BatchLoader.for(expanded_environment_name).batch(key: project_id) do |names, loader, args|
Environment.where(name: names, project: args[:key]).find_each do |environment|
loader.call(environment.name, environment)
end
end
end end
end end
......
...@@ -36,10 +36,12 @@ module EE ...@@ -36,10 +36,12 @@ module EE
def deployable_by_user? def deployable_by_user?
# We need to check if Protected Environments feature is available, # We need to check if Protected Environments feature is available,
# and whether there is an environment defined for the current build,
# as evaluating `build.expanded_environment_name` is expensive. # as evaluating `build.expanded_environment_name` is expensive.
return true unless build.has_environment?
return true unless build.project.protected_environments_feature_available? return true unless build.project.protected_environments_feature_available?
build.project.protected_environment_accessible_to?(build.persisted_environment&.name, user) build.project.protected_environment_accessible_to?(build.expanded_environment_name, user)
end end
end end
end end
......
---
title: Batch-load environments in EE pipelines
merge_request: 57706
author:
type: performance
...@@ -209,6 +209,25 @@ RSpec.describe PipelineSerializer do ...@@ -209,6 +209,25 @@ RSpec.describe PipelineSerializer do
end end
end end
context 'with build environments' do
let(:ref) { 'feature' }
it 'verifies number of queries', :request_store do
stub_licensed_features(protected_environments: true)
env = create(:environment, project: project)
create(:ci_build, :scheduled, project: project, environment: env.name)
create(:ci_build, :scheduled, project: project, environment: env.name)
create(:ci_build, :scheduled, project: project, environment: env.name)
recorded = ActiveRecord::QueryRecorder.new { subject }
expected_queries = Gitlab.ee? ? 61 : 57
expect(recorded.count).to be_within(1).of(expected_queries)
expect(recorded.cached_count).to eq(0)
end
end
context 'with scheduled and manual builds' do context 'with scheduled and manual builds' do
let(:ref) { 'feature' } let(:ref) { 'feature' }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment