Commit 2a53291a authored by Adam Hegyi's avatar Adam Hegyi

Use CTE for looking up projects with shared runners enabled

This change optionally wraps the namespace lookup with a CTE to act as
an optimization fence and prevent bad PG query planning. The change is
behind a feature flag:
use_cte_for_any_project_with_shared_runners_enabled
parent 318cfe28
---
name: use_cte_for_any_project_with_shared_runners_enabled
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71452
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342024
milestone: '14.4'
type: development
group: group::optimize
default_enabled: false
...@@ -260,10 +260,10 @@ module EE ...@@ -260,10 +260,10 @@ module EE
def any_project_with_shared_runners_enabled? def any_project_with_shared_runners_enabled?
if ::Feature.enabled?(:cache_shared_runners_enabled, self, default_enabled: :yaml) if ::Feature.enabled?(:cache_shared_runners_enabled, self, default_enabled: :yaml)
Rails.cache.fetch([self, :has_project_with_shared_runners_enabled], expires_in: 5.minutes) do Rails.cache.fetch([self, :has_project_with_shared_runners_enabled], expires_in: 5.minutes) do
all_projects.with_shared_runners.any? any_project_with_shared_runners_enabled_with_cte?
end end
else else
all_projects.with_shared_runners.any? any_project_with_shared_runners_enabled_with_cte?
end end
end end
...@@ -420,6 +420,25 @@ module EE ...@@ -420,6 +420,25 @@ module EE
private private
def any_project_with_shared_runners_enabled_with_cte?
if ::Feature.enabled?(:use_cte_for_any_project_with_shared_runners_enabled, self, default_enabled: :yaml)
projects_query = if user_namespace?
projects
else
cte = ::Gitlab::SQL::CTE.new(:namespace_self_and_descendants_cte, self_and_descendant_ids)
::Project
.with(cte.to_arel)
.from([::Project.table_name, cte.table.name].join(', '))
.where(::Project.arel_table[:namespace_id].eq(cte.table[:id]))
end
projects_query.with_shared_runners.any?
else
all_projects.with_shared_runners.any?
end
end
def fallback_plan def fallback_plan
if ::Gitlab.com? if ::Gitlab.com?
::Plan.free ::Plan.free
......
...@@ -638,6 +638,7 @@ RSpec.describe Namespace do ...@@ -638,6 +638,7 @@ RSpec.describe Namespace do
describe '#any_project_with_shared_runners_enabled?' do describe '#any_project_with_shared_runners_enabled?' do
subject { namespace.any_project_with_shared_runners_enabled? } subject { namespace.any_project_with_shared_runners_enabled? }
shared_examples '#any_project_with_shared_runners_enabled? examples' do
context 'without projects' do context 'without projects' do
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
end end
...@@ -667,6 +668,31 @@ RSpec.describe Namespace do ...@@ -667,6 +668,31 @@ RSpec.describe Namespace do
end end
end end
context 'when use_cte_for_any_project_with_shared_runners_enabled is enabled' do
before do
stub_feature_flags(use_cte_for_any_project_with_shared_runners_enabled: true)
end
it_behaves_like '#any_project_with_shared_runners_enabled? examples' do
it 'creates a CTE' do
group = create(:group)
expect(Gitlab::SQL::CTE).to receive(:new).and_call_original
group.any_project_with_shared_runners_enabled?
end
end
end
context 'when use_cte_for_any_project_with_shared_runners_enabled is disabled' do
before do
stub_feature_flags(use_cte_for_any_project_with_shared_runners_enabled: false)
end
it_behaves_like '#any_project_with_shared_runners_enabled? examples'
end
end
describe '#shared_runners_minutes_limit_enabled?' do describe '#shared_runners_minutes_limit_enabled?' do
subject { namespace.shared_runners_minutes_limit_enabled? } subject { namespace.shared_runners_minutes_limit_enabled? }
......
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