From 4c60207ab660a4b11b0c1ce74c0a8b82eed904d1 Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 8 Oct 2025 15:12:09 +0530 Subject: [PATCH 01/13] Remove epic and issue instance proxy --- .rubocop_todo/gitlab/bounded_contexts.yml | 3 - .rubocop_todo/rspec/named_subject.yml | 1 - .rubocop_todo/search/namespaced_class.yml | 3 - ee/lib/elastic/latest/epic_instance_proxy.rb | 50 ------------ ee/lib/elastic/latest/issue_instance_proxy.rb | 57 -------------- .../latest/epic_instance_proxy_spec.rb | 77 ------------------- 6 files changed, 191 deletions(-) delete mode 100644 ee/lib/elastic/latest/epic_instance_proxy.rb delete mode 100644 ee/lib/elastic/latest/issue_instance_proxy.rb delete mode 100644 ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb diff --git a/.rubocop_todo/gitlab/bounded_contexts.yml b/.rubocop_todo/gitlab/bounded_contexts.yml index b6fdb62c596e2e..ea595b8216f800 100644 --- a/.rubocop_todo/gitlab/bounded_contexts.yml +++ b/.rubocop_todo/gitlab/bounded_contexts.yml @@ -3529,13 +3529,10 @@ Gitlab/BoundedContexts: - 'ee/lib/elastic/latest/config.rb' - 'ee/lib/elastic/latest/custom_language_analyzers.rb' - 'ee/lib/elastic/latest/document_should_be_deleted_from_index_error.rb' - - 'ee/lib/elastic/latest/epic_class_proxy.rb' - 'ee/lib/elastic/latest/epic_config.rb' - - 'ee/lib/elastic/latest/epic_instance_proxy.rb' - 'ee/lib/elastic/latest/git_class_proxy.rb' - 'ee/lib/elastic/latest/git_instance_proxy.rb' - 'ee/lib/elastic/latest/issue_config.rb' - - 'ee/lib/elastic/latest/issue_instance_proxy.rb' - 'ee/lib/elastic/latest/merge_request_class_proxy.rb' - 'ee/lib/elastic/latest/merge_request_config.rb' - 'ee/lib/elastic/latest/merge_request_instance_proxy.rb' diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml index e8ab67a7e962c5..5bbcfef578d67e 100644 --- a/.rubocop_todo/rspec/named_subject.yml +++ b/.rubocop_todo/rspec/named_subject.yml @@ -261,7 +261,6 @@ RSpec/NamedSubject: - 'ee/spec/lib/ee/sidebars/projects/menus/security_compliance_menu_spec.rb' - 'ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb' - 'ee/spec/lib/elastic/latest/application_instance_proxy_spec.rb' - - 'ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb' - 'ee/spec/lib/elastic/latest/git_instance_proxy_spec.rb' - 'ee/spec/lib/elastic/latest/routing_spec.rb' - 'ee/spec/lib/elastic/latest/snippet_instance_proxy_spec.rb' diff --git a/.rubocop_todo/search/namespaced_class.yml b/.rubocop_todo/search/namespaced_class.yml index 124335850598cf..e112b1627e58fd 100644 --- a/.rubocop_todo/search/namespaced_class.yml +++ b/.rubocop_todo/search/namespaced_class.yml @@ -74,13 +74,10 @@ Search/NamespacedClass: - 'ee/lib/elastic/latest/config.rb' - 'ee/lib/elastic/latest/custom_language_analyzers.rb' - 'ee/lib/elastic/latest/document_should_be_deleted_from_index_error.rb' - - 'ee/lib/elastic/latest/epic_class_proxy.rb' - 'ee/lib/elastic/latest/epic_config.rb' - - 'ee/lib/elastic/latest/epic_instance_proxy.rb' - 'ee/lib/elastic/latest/git_class_proxy.rb' - 'ee/lib/elastic/latest/git_instance_proxy.rb' - 'ee/lib/elastic/latest/issue_config.rb' - - 'ee/lib/elastic/latest/issue_instance_proxy.rb' - 'ee/lib/elastic/latest/merge_request_class_proxy.rb' - 'ee/lib/elastic/latest/merge_request_config.rb' - 'ee/lib/elastic/latest/merge_request_instance_proxy.rb' diff --git a/ee/lib/elastic/latest/epic_instance_proxy.rb b/ee/lib/elastic/latest/epic_instance_proxy.rb deleted file mode 100644 index b335772b9d1fae..00000000000000 --- a/ee/lib/elastic/latest/epic_instance_proxy.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -module Elastic - module Latest - class EpicInstanceProxy < ApplicationInstanceProxy - SCHEMA_VERSION = 24_01 - - def as_indexed_json(_options = {}) - data = {} - - [ - :id, - :iid, - :group_id, - :created_at, - :updated_at, - :title, - :description, - :state, - :confidential, - :author_id - ].each do |attr| - data[attr.to_s] = safely_read_attribute_for_elasticsearch(attr) - end - - data['label_ids'] = target.label_ids.map(&:to_s) - data['start_date'] = target.start_date || target.start_date_from_inherited_source - data['due_date'] = target.end_date || target.due_date_from_inherited_source - - data['traversal_ids'] = target.group.elastic_namespace_ancestry - data['hashed_root_namespace_id'] = target.group.hashed_root_namespace_id - data['visibility_level'] = target.group.visibility_level - - # Schema version. The format is Date.today.strftime('%y_%m') - # Please update if you're changing the schema of the document - data['schema_version'] = SCHEMA_VERSION - - data.merge(generic_attributes) - end - - def generic_attributes - super.except('join_field') - end - - def es_parent - "group_#{group.root_ancestor.id}" - end - end - end -end diff --git a/ee/lib/elastic/latest/issue_instance_proxy.rb b/ee/lib/elastic/latest/issue_instance_proxy.rb deleted file mode 100644 index 9cb46e459eccaf..00000000000000 --- a/ee/lib/elastic/latest/issue_instance_proxy.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -module Elastic - module Latest - class IssueInstanceProxy < ApplicationInstanceProxy - SCHEMA_VERSION = 24_08 - OPTIONAL_FIELDS = %w[embedding embedding_version].freeze - - def as_indexed_json(_options = {}) - data = {} - - return data unless target.project_id - - # We don't use as_json(only: ...) because it calls all virtual and serialized attributes - # https://gitlab.com/gitlab-org/gitlab/issues/349 - [:id, :iid, :title, :description, :created_at, :updated_at, :state, :project_id, :author_id, - :confidential].each do |attr| - data[attr.to_s] = safely_read_attribute_for_elasticsearch(attr) - end - - # Schema version. The format is Date.today.strftime('%y_%m') - # Please update if you're changing the schema of the document - data['schema_version'] = SCHEMA_VERSION - - # Load them through the issue_assignees table since calling - # assignee_ids can't be easily preloaded and does - # unnecessary joins - data['assignee_id'] = safely_read_attribute_for_elasticsearch(:issue_assignee_user_ids) - data['hidden'] = target.hidden? - data['visibility_level'] = target.project.visibility_level - data['issues_access_level'] = safely_read_project_feature_for_elasticsearch(:issues) - - data['upvotes'] = target.upvotes_count - data['namespace_ancestry_ids'] = target.namespace_ancestry - data['label_ids'] = target.label_ids.map(&:to_s) - - data['hashed_root_namespace_id'] = target.project.namespace.hashed_root_namespace_id - data['archived'] = target.project.archived? - data['work_item_type_id'] = target.work_item_type_id - - data['routing'] = es_parent - - data.merge(generic_attributes) - end - - def es_id - target.id.to_s - end - - private - - def generic_attributes - super.except('join_field') - end - end - end -end diff --git a/ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb b/ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb deleted file mode 100644 index 381c66edb434d3..00000000000000 --- a/ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Elastic::Latest::EpicInstanceProxy, feature_category: :global_search do - let_it_be(:parent_group) { create(:group) } - let_it_be(:group) { create(:group, parent: parent_group) } - let_it_be(:label) { create(:group_label, group: group) } - let_it_be(:epic) { create(:labeled_epic, :use_fixed_dates, :opened, group: group, labels: [label]) } - - subject { described_class.new(epic) } - - describe '#as_indexed_json' do - let(:result) { subject.as_indexed_json.with_indifferent_access } - - it 'serializes the object as a hash' do - expect(result).to include( - id: epic.id, - iid: epic.iid, - group_id: group.id, - created_at: epic.created_at, - updated_at: epic.updated_at, - title: epic.title, - description: epic.description, - state: 'opened', - confidential: epic.confidential, - author_id: epic.author_id, - label_ids: [label.id.to_s], - start_date: epic.start_date, - due_date: epic.due_date, - traversal_ids: "#{parent_group.id}-#{group.id}-", - hashed_root_namespace_id: ::Search.hash_namespace_id(parent_group.id), - visibility_level: group.visibility_level, - schema_version: described_class::SCHEMA_VERSION, - type: 'epic' - ) - end - - it 'does not have an N+1 for building the document' do - epic = create(:epic, group: group) - - control = ActiveRecord::QueryRecorder.new do - epic.__elasticsearch__.as_indexed_json - end - - group_with_parent = create(:group, :private, parent: group) - epic.update!(group_id: group_with_parent.id) - - expect do - epic.__elasticsearch__.as_indexed_json - end.not_to exceed_query_limit(control) - end - - context 'with start date inherited date from child epic and due date inherited from milestone' do - let_it_be(:epic) { create(:epic) } - let_it_be(:child_epic) { create(:epic, :use_fixed_dates) } - let_it_be(:milestone) { create(:milestone, :with_dates) } - - before do - epic.start_date_sourcing_epic = child_epic - epic.due_date_sourcing_milestone = milestone - epic.save! - end - - it 'sets start and due dates to inherited dates' do - expect(result[:start_date]).to eq(child_epic.start_date) - expect(result[:due_date]).to eq(milestone.due_date) - end - end - end - - describe '#es_parent' do - it 'contains group id' do - expect(subject.es_parent).to eq("group_#{parent_group.id}") - end - end -end -- GitLab From 50a913b7296033c201e8f51309ce1abc9cb5adff Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 8 Oct 2025 17:24:43 +0530 Subject: [PATCH 02/13] Refactor multi_version_util and class_proxy_util --- ee/lib/elastic/class_proxy_util.rb | 3 ++- ee/lib/elastic/multi_version_class_proxy.rb | 4 ++++ ee/lib/elastic/multi_version_instance_proxy.rb | 4 ++++ ee/lib/elastic/multi_version_util.rb | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ee/lib/elastic/class_proxy_util.rb b/ee/lib/elastic/class_proxy_util.rb index 807a25b3fe1f8a..c8d773328950f7 100644 --- a/ee/lib/elastic/class_proxy_util.rb +++ b/ee/lib/elastic/class_proxy_util.rb @@ -13,7 +13,8 @@ def initialize(target, use_separate_indices: false) # use_separate_indices check is needed to load custom mappings for AR and non-AR classes # For example, Issue and Commit - const_name = use_separate_indices ? "#{target.base_class}Config" : 'Config' + target_class = target.is_a?(Class) ? target : target.class + const_name = use_separate_indices ? "#{target_class.base_class}Config" : 'Config' config = version_namespace.const_get(const_name, false) diff --git a/ee/lib/elastic/multi_version_class_proxy.rb b/ee/lib/elastic/multi_version_class_proxy.rb index 5dcedcaba4f628..a591eab2c6a48c 100644 --- a/ee/lib/elastic/multi_version_class_proxy.rb +++ b/ee/lib/elastic/multi_version_class_proxy.rb @@ -25,5 +25,9 @@ def version(version) def proxy_class_name "#{@data_class.name}ClassProxy" end + + def fallback_proxy_class_name + :ApplicationClassProxy + end end end diff --git a/ee/lib/elastic/multi_version_instance_proxy.rb b/ee/lib/elastic/multi_version_instance_proxy.rb index 5758a57760eb60..de12e14bd29d0c 100644 --- a/ee/lib/elastic/multi_version_instance_proxy.rb +++ b/ee/lib/elastic/multi_version_instance_proxy.rb @@ -18,5 +18,9 @@ def initialize(data_target, use_separate_indices: false) def proxy_class_name "#{@data_class.name}InstanceProxy" end + + def fallback_proxy_class_name + :ApplicationInstanceProxy + end end end diff --git a/ee/lib/elastic/multi_version_util.rb b/ee/lib/elastic/multi_version_util.rb index ce16125f0bea80..e29e5c18480150 100644 --- a/ee/lib/elastic/multi_version_util.rb +++ b/ee/lib/elastic/multi_version_util.rb @@ -17,7 +17,7 @@ def version(version) proxy_class = if version.const_defined?(proxy_class_name, false) version.const_get(proxy_class_name, false) else - version.const_get(:ApplicationClassProxy, false) + version.const_get(fallback_proxy_class_name, false) end proxy_class.new(data_target, use_separate_indices: use_separate_indices) -- GitLab From b4043d123d2fbfb50a2e0a0e09d7e12077aa5867 Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 8 Oct 2025 19:19:37 +0530 Subject: [PATCH 03/13] Fix failing specs --- ee/lib/elastic/class_proxy_util.rb | 2 +- ee/lib/gitlab/elastic/helper.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ee/lib/elastic/class_proxy_util.rb b/ee/lib/elastic/class_proxy_util.rb index c8d773328950f7..17794d1467e0a8 100644 --- a/ee/lib/elastic/class_proxy_util.rb +++ b/ee/lib/elastic/class_proxy_util.rb @@ -14,7 +14,7 @@ def initialize(target, use_separate_indices: false) # use_separate_indices check is needed to load custom mappings for AR and non-AR classes # For example, Issue and Commit target_class = target.is_a?(Class) ? target : target.class - const_name = use_separate_indices ? "#{target_class.base_class}Config" : 'Config' + const_name = use_separate_indices ? "#{target_class.try(:base_class) || target_class}Config" : 'Config' config = version_namespace.const_get(const_name, false) diff --git a/ee/lib/gitlab/elastic/helper.rb b/ee/lib/gitlab/elastic/helper.rb index 318626ab64b6da..7d32d961e1167f 100644 --- a/ee/lib/gitlab/elastic/helper.rb +++ b/ee/lib/gitlab/elastic/helper.rb @@ -364,6 +364,9 @@ def target_index_names(target:) def klass_to_alias_name(klass:) return target_name if klass == Repository + # If klass is already a proxy object, just return its index_name + return klass.index_name if klass.is_a?(::Elasticsearch::Model::Proxy::ClassMethodsProxy) + proxy_klass = self.class.type_class(klass) || ::Elastic::Latest::ApplicationClassProxy.new(klass, use_separate_indices: true) proxy_klass.index_name -- GitLab From 111b9fbb000f65a33186b0f63b79c5adbc0e6503 Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 8 Oct 2025 15:12:09 +0530 Subject: [PATCH 04/13] Remove epic and issue instance proxy --- .rubocop_todo/gitlab/bounded_contexts.yml | 2 - .rubocop_todo/rspec/named_subject.yml | 1 - .rubocop_todo/search/namespaced_class.yml | 2 - ee/lib/elastic/latest/epic_instance_proxy.rb | 50 ------------ ee/lib/elastic/latest/issue_instance_proxy.rb | 57 -------------- .../latest/epic_instance_proxy_spec.rb | 77 ------------------- 6 files changed, 189 deletions(-) delete mode 100644 ee/lib/elastic/latest/epic_instance_proxy.rb delete mode 100644 ee/lib/elastic/latest/issue_instance_proxy.rb delete mode 100644 ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb diff --git a/.rubocop_todo/gitlab/bounded_contexts.yml b/.rubocop_todo/gitlab/bounded_contexts.yml index c7736232911350..ea595b8216f800 100644 --- a/.rubocop_todo/gitlab/bounded_contexts.yml +++ b/.rubocop_todo/gitlab/bounded_contexts.yml @@ -3530,11 +3530,9 @@ Gitlab/BoundedContexts: - 'ee/lib/elastic/latest/custom_language_analyzers.rb' - 'ee/lib/elastic/latest/document_should_be_deleted_from_index_error.rb' - 'ee/lib/elastic/latest/epic_config.rb' - - 'ee/lib/elastic/latest/epic_instance_proxy.rb' - 'ee/lib/elastic/latest/git_class_proxy.rb' - 'ee/lib/elastic/latest/git_instance_proxy.rb' - 'ee/lib/elastic/latest/issue_config.rb' - - 'ee/lib/elastic/latest/issue_instance_proxy.rb' - 'ee/lib/elastic/latest/merge_request_class_proxy.rb' - 'ee/lib/elastic/latest/merge_request_config.rb' - 'ee/lib/elastic/latest/merge_request_instance_proxy.rb' diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml index e8ab67a7e962c5..5bbcfef578d67e 100644 --- a/.rubocop_todo/rspec/named_subject.yml +++ b/.rubocop_todo/rspec/named_subject.yml @@ -261,7 +261,6 @@ RSpec/NamedSubject: - 'ee/spec/lib/ee/sidebars/projects/menus/security_compliance_menu_spec.rb' - 'ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb' - 'ee/spec/lib/elastic/latest/application_instance_proxy_spec.rb' - - 'ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb' - 'ee/spec/lib/elastic/latest/git_instance_proxy_spec.rb' - 'ee/spec/lib/elastic/latest/routing_spec.rb' - 'ee/spec/lib/elastic/latest/snippet_instance_proxy_spec.rb' diff --git a/.rubocop_todo/search/namespaced_class.yml b/.rubocop_todo/search/namespaced_class.yml index 402cca32971580..e112b1627e58fd 100644 --- a/.rubocop_todo/search/namespaced_class.yml +++ b/.rubocop_todo/search/namespaced_class.yml @@ -75,11 +75,9 @@ Search/NamespacedClass: - 'ee/lib/elastic/latest/custom_language_analyzers.rb' - 'ee/lib/elastic/latest/document_should_be_deleted_from_index_error.rb' - 'ee/lib/elastic/latest/epic_config.rb' - - 'ee/lib/elastic/latest/epic_instance_proxy.rb' - 'ee/lib/elastic/latest/git_class_proxy.rb' - 'ee/lib/elastic/latest/git_instance_proxy.rb' - 'ee/lib/elastic/latest/issue_config.rb' - - 'ee/lib/elastic/latest/issue_instance_proxy.rb' - 'ee/lib/elastic/latest/merge_request_class_proxy.rb' - 'ee/lib/elastic/latest/merge_request_config.rb' - 'ee/lib/elastic/latest/merge_request_instance_proxy.rb' diff --git a/ee/lib/elastic/latest/epic_instance_proxy.rb b/ee/lib/elastic/latest/epic_instance_proxy.rb deleted file mode 100644 index b335772b9d1fae..00000000000000 --- a/ee/lib/elastic/latest/epic_instance_proxy.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -module Elastic - module Latest - class EpicInstanceProxy < ApplicationInstanceProxy - SCHEMA_VERSION = 24_01 - - def as_indexed_json(_options = {}) - data = {} - - [ - :id, - :iid, - :group_id, - :created_at, - :updated_at, - :title, - :description, - :state, - :confidential, - :author_id - ].each do |attr| - data[attr.to_s] = safely_read_attribute_for_elasticsearch(attr) - end - - data['label_ids'] = target.label_ids.map(&:to_s) - data['start_date'] = target.start_date || target.start_date_from_inherited_source - data['due_date'] = target.end_date || target.due_date_from_inherited_source - - data['traversal_ids'] = target.group.elastic_namespace_ancestry - data['hashed_root_namespace_id'] = target.group.hashed_root_namespace_id - data['visibility_level'] = target.group.visibility_level - - # Schema version. The format is Date.today.strftime('%y_%m') - # Please update if you're changing the schema of the document - data['schema_version'] = SCHEMA_VERSION - - data.merge(generic_attributes) - end - - def generic_attributes - super.except('join_field') - end - - def es_parent - "group_#{group.root_ancestor.id}" - end - end - end -end diff --git a/ee/lib/elastic/latest/issue_instance_proxy.rb b/ee/lib/elastic/latest/issue_instance_proxy.rb deleted file mode 100644 index 9cb46e459eccaf..00000000000000 --- a/ee/lib/elastic/latest/issue_instance_proxy.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -module Elastic - module Latest - class IssueInstanceProxy < ApplicationInstanceProxy - SCHEMA_VERSION = 24_08 - OPTIONAL_FIELDS = %w[embedding embedding_version].freeze - - def as_indexed_json(_options = {}) - data = {} - - return data unless target.project_id - - # We don't use as_json(only: ...) because it calls all virtual and serialized attributes - # https://gitlab.com/gitlab-org/gitlab/issues/349 - [:id, :iid, :title, :description, :created_at, :updated_at, :state, :project_id, :author_id, - :confidential].each do |attr| - data[attr.to_s] = safely_read_attribute_for_elasticsearch(attr) - end - - # Schema version. The format is Date.today.strftime('%y_%m') - # Please update if you're changing the schema of the document - data['schema_version'] = SCHEMA_VERSION - - # Load them through the issue_assignees table since calling - # assignee_ids can't be easily preloaded and does - # unnecessary joins - data['assignee_id'] = safely_read_attribute_for_elasticsearch(:issue_assignee_user_ids) - data['hidden'] = target.hidden? - data['visibility_level'] = target.project.visibility_level - data['issues_access_level'] = safely_read_project_feature_for_elasticsearch(:issues) - - data['upvotes'] = target.upvotes_count - data['namespace_ancestry_ids'] = target.namespace_ancestry - data['label_ids'] = target.label_ids.map(&:to_s) - - data['hashed_root_namespace_id'] = target.project.namespace.hashed_root_namespace_id - data['archived'] = target.project.archived? - data['work_item_type_id'] = target.work_item_type_id - - data['routing'] = es_parent - - data.merge(generic_attributes) - end - - def es_id - target.id.to_s - end - - private - - def generic_attributes - super.except('join_field') - end - end - end -end diff --git a/ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb b/ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb deleted file mode 100644 index 381c66edb434d3..00000000000000 --- a/ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Elastic::Latest::EpicInstanceProxy, feature_category: :global_search do - let_it_be(:parent_group) { create(:group) } - let_it_be(:group) { create(:group, parent: parent_group) } - let_it_be(:label) { create(:group_label, group: group) } - let_it_be(:epic) { create(:labeled_epic, :use_fixed_dates, :opened, group: group, labels: [label]) } - - subject { described_class.new(epic) } - - describe '#as_indexed_json' do - let(:result) { subject.as_indexed_json.with_indifferent_access } - - it 'serializes the object as a hash' do - expect(result).to include( - id: epic.id, - iid: epic.iid, - group_id: group.id, - created_at: epic.created_at, - updated_at: epic.updated_at, - title: epic.title, - description: epic.description, - state: 'opened', - confidential: epic.confidential, - author_id: epic.author_id, - label_ids: [label.id.to_s], - start_date: epic.start_date, - due_date: epic.due_date, - traversal_ids: "#{parent_group.id}-#{group.id}-", - hashed_root_namespace_id: ::Search.hash_namespace_id(parent_group.id), - visibility_level: group.visibility_level, - schema_version: described_class::SCHEMA_VERSION, - type: 'epic' - ) - end - - it 'does not have an N+1 for building the document' do - epic = create(:epic, group: group) - - control = ActiveRecord::QueryRecorder.new do - epic.__elasticsearch__.as_indexed_json - end - - group_with_parent = create(:group, :private, parent: group) - epic.update!(group_id: group_with_parent.id) - - expect do - epic.__elasticsearch__.as_indexed_json - end.not_to exceed_query_limit(control) - end - - context 'with start date inherited date from child epic and due date inherited from milestone' do - let_it_be(:epic) { create(:epic) } - let_it_be(:child_epic) { create(:epic, :use_fixed_dates) } - let_it_be(:milestone) { create(:milestone, :with_dates) } - - before do - epic.start_date_sourcing_epic = child_epic - epic.due_date_sourcing_milestone = milestone - epic.save! - end - - it 'sets start and due dates to inherited dates' do - expect(result[:start_date]).to eq(child_epic.start_date) - expect(result[:due_date]).to eq(milestone.due_date) - end - end - end - - describe '#es_parent' do - it 'contains group id' do - expect(subject.es_parent).to eq("group_#{parent_group.id}") - end - end -end -- GitLab From b5eddc0d1625e86f9f478b8bf6d61d5e79747d85 Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 8 Oct 2025 17:24:43 +0530 Subject: [PATCH 05/13] Refactor multi_version_util and class_proxy_util --- ee/lib/elastic/class_proxy_util.rb | 3 ++- ee/lib/elastic/multi_version_class_proxy.rb | 4 ++++ ee/lib/elastic/multi_version_instance_proxy.rb | 4 ++++ ee/lib/elastic/multi_version_util.rb | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ee/lib/elastic/class_proxy_util.rb b/ee/lib/elastic/class_proxy_util.rb index 807a25b3fe1f8a..c8d773328950f7 100644 --- a/ee/lib/elastic/class_proxy_util.rb +++ b/ee/lib/elastic/class_proxy_util.rb @@ -13,7 +13,8 @@ def initialize(target, use_separate_indices: false) # use_separate_indices check is needed to load custom mappings for AR and non-AR classes # For example, Issue and Commit - const_name = use_separate_indices ? "#{target.base_class}Config" : 'Config' + target_class = target.is_a?(Class) ? target : target.class + const_name = use_separate_indices ? "#{target_class.base_class}Config" : 'Config' config = version_namespace.const_get(const_name, false) diff --git a/ee/lib/elastic/multi_version_class_proxy.rb b/ee/lib/elastic/multi_version_class_proxy.rb index 5dcedcaba4f628..a591eab2c6a48c 100644 --- a/ee/lib/elastic/multi_version_class_proxy.rb +++ b/ee/lib/elastic/multi_version_class_proxy.rb @@ -25,5 +25,9 @@ def version(version) def proxy_class_name "#{@data_class.name}ClassProxy" end + + def fallback_proxy_class_name + :ApplicationClassProxy + end end end diff --git a/ee/lib/elastic/multi_version_instance_proxy.rb b/ee/lib/elastic/multi_version_instance_proxy.rb index 5758a57760eb60..de12e14bd29d0c 100644 --- a/ee/lib/elastic/multi_version_instance_proxy.rb +++ b/ee/lib/elastic/multi_version_instance_proxy.rb @@ -18,5 +18,9 @@ def initialize(data_target, use_separate_indices: false) def proxy_class_name "#{@data_class.name}InstanceProxy" end + + def fallback_proxy_class_name + :ApplicationInstanceProxy + end end end diff --git a/ee/lib/elastic/multi_version_util.rb b/ee/lib/elastic/multi_version_util.rb index ce16125f0bea80..e29e5c18480150 100644 --- a/ee/lib/elastic/multi_version_util.rb +++ b/ee/lib/elastic/multi_version_util.rb @@ -17,7 +17,7 @@ def version(version) proxy_class = if version.const_defined?(proxy_class_name, false) version.const_get(proxy_class_name, false) else - version.const_get(:ApplicationClassProxy, false) + version.const_get(fallback_proxy_class_name, false) end proxy_class.new(data_target, use_separate_indices: use_separate_indices) -- GitLab From c157782f679038811815d147e18855136b62b35a Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 8 Oct 2025 19:19:37 +0530 Subject: [PATCH 06/13] Fix failing specs --- ee/lib/elastic/class_proxy_util.rb | 2 +- ee/lib/gitlab/elastic/helper.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ee/lib/elastic/class_proxy_util.rb b/ee/lib/elastic/class_proxy_util.rb index c8d773328950f7..17794d1467e0a8 100644 --- a/ee/lib/elastic/class_proxy_util.rb +++ b/ee/lib/elastic/class_proxy_util.rb @@ -14,7 +14,7 @@ def initialize(target, use_separate_indices: false) # use_separate_indices check is needed to load custom mappings for AR and non-AR classes # For example, Issue and Commit target_class = target.is_a?(Class) ? target : target.class - const_name = use_separate_indices ? "#{target_class.base_class}Config" : 'Config' + const_name = use_separate_indices ? "#{target_class.try(:base_class) || target_class}Config" : 'Config' config = version_namespace.const_get(const_name, false) diff --git a/ee/lib/gitlab/elastic/helper.rb b/ee/lib/gitlab/elastic/helper.rb index 318626ab64b6da..7d32d961e1167f 100644 --- a/ee/lib/gitlab/elastic/helper.rb +++ b/ee/lib/gitlab/elastic/helper.rb @@ -364,6 +364,9 @@ def target_index_names(target:) def klass_to_alias_name(klass:) return target_name if klass == Repository + # If klass is already a proxy object, just return its index_name + return klass.index_name if klass.is_a?(::Elasticsearch::Model::Proxy::ClassMethodsProxy) + proxy_klass = self.class.type_class(klass) || ::Elastic::Latest::ApplicationClassProxy.new(klass, use_separate_indices: true) proxy_klass.index_name -- GitLab From 279e5911d126eee33327d35c9af2f6eabacb042c Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Thu, 9 Oct 2025 10:34:21 +0530 Subject: [PATCH 07/13] Refactor klass_to_alias_name method --- ee/lib/gitlab/elastic/helper.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ee/lib/gitlab/elastic/helper.rb b/ee/lib/gitlab/elastic/helper.rb index 7d32d961e1167f..96ad686c2149cc 100644 --- a/ee/lib/gitlab/elastic/helper.rb +++ b/ee/lib/gitlab/elastic/helper.rb @@ -367,9 +367,8 @@ def klass_to_alias_name(klass:) # If klass is already a proxy object, just return its index_name return klass.index_name if klass.is_a?(::Elasticsearch::Model::Proxy::ClassMethodsProxy) - proxy_klass = self.class.type_class(klass) || ::Elastic::Latest::ApplicationClassProxy.new(klass, - use_separate_indices: true) - proxy_klass.index_name + (self.class.type_class(klass) || ::Elastic::Latest::ApplicationClassProxy.new(klass, + use_separate_indices: true)).index_name end # handles unreachable hosts and any other exceptions that may be raised -- GitLab From fd20e4bcedb395bf523fcdc2a705e5e0bec7fc87 Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Thu, 9 Oct 2025 22:25:07 +0530 Subject: [PATCH 08/13] Add patch suggested by @terrichu --- .rubocop_todo/gitlab/bounded_contexts.yml | 2 - .rubocop_todo/search/namespaced_class.yml | 2 - .../concerns/search/elastic/issues_search.rb | 4 ++ ee/app/models/ee/epic.rb | 5 -- ee/app/models/ee/issue.rb | 9 ++-- ee/lib/elastic/class_proxy_util.rb | 4 +- ee/lib/elastic/latest/epic_config.rb | 43 --------------- ee/lib/elastic/latest/issue_config.rb | 52 ------------------- ee/lib/elastic/multi_version_class_proxy.rb | 4 -- .../elastic/multi_version_instance_proxy.rb | 4 -- ee/lib/elastic/multi_version_util.rb | 3 +- ee/lib/gitlab/elastic/document_reference.rb | 2 +- ee/lib/gitlab/elastic/helper.rb | 2 - ee/lib/search/elastic/references/work_item.rb | 2 + 14 files changed, 13 insertions(+), 125 deletions(-) delete mode 100644 ee/lib/elastic/latest/epic_config.rb delete mode 100644 ee/lib/elastic/latest/issue_config.rb diff --git a/.rubocop_todo/gitlab/bounded_contexts.yml b/.rubocop_todo/gitlab/bounded_contexts.yml index ea595b8216f800..a225956af4e543 100644 --- a/.rubocop_todo/gitlab/bounded_contexts.yml +++ b/.rubocop_todo/gitlab/bounded_contexts.yml @@ -3529,10 +3529,8 @@ Gitlab/BoundedContexts: - 'ee/lib/elastic/latest/config.rb' - 'ee/lib/elastic/latest/custom_language_analyzers.rb' - 'ee/lib/elastic/latest/document_should_be_deleted_from_index_error.rb' - - 'ee/lib/elastic/latest/epic_config.rb' - 'ee/lib/elastic/latest/git_class_proxy.rb' - 'ee/lib/elastic/latest/git_instance_proxy.rb' - - 'ee/lib/elastic/latest/issue_config.rb' - 'ee/lib/elastic/latest/merge_request_class_proxy.rb' - 'ee/lib/elastic/latest/merge_request_config.rb' - 'ee/lib/elastic/latest/merge_request_instance_proxy.rb' diff --git a/.rubocop_todo/search/namespaced_class.yml b/.rubocop_todo/search/namespaced_class.yml index e112b1627e58fd..e7c31ab65bfc59 100644 --- a/.rubocop_todo/search/namespaced_class.yml +++ b/.rubocop_todo/search/namespaced_class.yml @@ -74,10 +74,8 @@ Search/NamespacedClass: - 'ee/lib/elastic/latest/config.rb' - 'ee/lib/elastic/latest/custom_language_analyzers.rb' - 'ee/lib/elastic/latest/document_should_be_deleted_from_index_error.rb' - - 'ee/lib/elastic/latest/epic_config.rb' - 'ee/lib/elastic/latest/git_class_proxy.rb' - 'ee/lib/elastic/latest/git_instance_proxy.rb' - - 'ee/lib/elastic/latest/issue_config.rb' - 'ee/lib/elastic/latest/merge_request_class_proxy.rb' - 'ee/lib/elastic/latest/merge_request_config.rb' - 'ee/lib/elastic/latest/merge_request_instance_proxy.rb' diff --git a/ee/app/models/concerns/search/elastic/issues_search.rb b/ee/app/models/concerns/search/elastic/issues_search.rb index e49a1b930d9b49..589d361eccb740 100644 --- a/ee/app/models/concerns/search/elastic/issues_search.rb +++ b/ee/app/models/concerns/search/elastic/issues_search.rb @@ -24,6 +24,10 @@ def maintain_elasticsearch_update(updated_attributes: previous_changes.keys) track_embedding! if (updated_attributes.map(&:to_sym) & EMBEDDING_TRACKED_FIELDS).any? && track_embedding? end + def es_id + ::Gitlab::Elastic::Helper.build_es_id(es_type: es_type, target_id: id) + end + private # rubocop: disable Gitlab/FeatureFlagWithoutActor -- global flags diff --git a/ee/app/models/ee/epic.rb b/ee/app/models/ee/epic.rb index b5dd67a5f6386e..72a142c94391dc 100644 --- a/ee/app/models/ee/epic.rb +++ b/ee/app/models/ee/epic.rb @@ -370,11 +370,6 @@ def search(query) fuzzy_search(query, [:title, :description]) end - override :use_separate_indices? - def use_separate_indices? - true - end - def ids_for_base_and_decendants(epic_ids) ::Gitlab::ObjectHierarchy.new(self.id_in(epic_ids)).base_and_descendants.pluck(:id) end diff --git a/ee/app/models/ee/issue.rb b/ee/app/models/ee/issue.rb index 99edfda639a048..0f0958e3ae15a1 100644 --- a/ee/app/models/ee/issue.rb +++ b/ee/app/models/ee/issue.rb @@ -171,11 +171,6 @@ def with_api_entity_associations super.preload(:sync_object, epic: { group: :route }, iteration: { group: :route }) end - # override - def use_separate_indices? - true - end - # override def supported_keyset_orderings super.merge(weight: [:asc, :desc]) @@ -219,6 +214,10 @@ def elastic_reference ::Search::Elastic::References::WorkItem.serialize(self) end + def self.es_type + ::Search::Elastic::References::WorkItem::DOC_TYPE + end + override :maintain_elasticsearch_update def maintain_elasticsearch_update(updated_attributes: previous_changes.keys) super diff --git a/ee/lib/elastic/class_proxy_util.rb b/ee/lib/elastic/class_proxy_util.rb index 17794d1467e0a8..6b33e97189f58d 100644 --- a/ee/lib/elastic/class_proxy_util.rb +++ b/ee/lib/elastic/class_proxy_util.rb @@ -13,9 +13,7 @@ def initialize(target, use_separate_indices: false) # use_separate_indices check is needed to load custom mappings for AR and non-AR classes # For example, Issue and Commit - target_class = target.is_a?(Class) ? target : target.class - const_name = use_separate_indices ? "#{target_class.try(:base_class) || target_class}Config" : 'Config' - + const_name = use_separate_indices ? "#{target.base_class}Config" : 'Config' config = version_namespace.const_get(const_name, false) @index_name = config.index_name diff --git a/ee/lib/elastic/latest/epic_config.rb b/ee/lib/elastic/latest/epic_config.rb deleted file mode 100644 index 06200bd706cff6..00000000000000 --- a/ee/lib/elastic/latest/epic_config.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -module Elastic - module Latest - module EpicConfig - extend Elasticsearch::Model::Indexing::ClassMethods - extend Elasticsearch::Model::Naming::ClassMethods - - def self.index_name - [Gitlab::CurrentSettings.elasticsearch_prefix, Rails.env, 'epics'].join('-') - end - - settings Elastic::Latest::Config.settings.to_hash.deep_merge( - index: Elastic::Latest::Config.separate_index_specific_settings(index_name) - ) - - mappings dynamic: 'strict' do - indexes :id, type: :integer - indexes :iid, type: :integer - indexes :group_id, type: :long - - indexes :created_at, type: :date - indexes :updated_at, type: :date - - indexes :title, type: :text, index_options: 'positions', analyzer: :title_analyzer - indexes :description, type: :text, index_options: 'positions', analyzer: :code_analyzer - indexes :state, type: :keyword - indexes :confidential, type: :boolean - indexes :author_id, type: :integer - indexes :label_ids, type: :keyword - indexes :start_date, type: :date - indexes :due_date, type: :date - - indexes :traversal_ids, type: :keyword - indexes :hashed_root_namespace_id, type: :integer - indexes :visibility_level, type: :integer - - indexes :schema_version, type: :short - indexes :type, type: :keyword - end - end - end -end diff --git a/ee/lib/elastic/latest/issue_config.rb b/ee/lib/elastic/latest/issue_config.rb deleted file mode 100644 index 9986a3f9d9d92e..00000000000000 --- a/ee/lib/elastic/latest/issue_config.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -module Elastic - module Latest - module IssueConfig - # To obtain settings and mappings methods - extend Elasticsearch::Model::Indexing::ClassMethods - extend Elasticsearch::Model::Naming::ClassMethods - - def self.index_name - [Gitlab::CurrentSettings.elasticsearch_prefix, Rails.env, 'issues'].join('-') - end - - settings Elastic::Latest::Config.settings.to_hash.deep_merge( - index: { - number_of_shards: Elastic::AsJSON.new { Elastic::IndexSetting[index_name].number_of_shards }, - number_of_replicas: Elastic::AsJSON.new { Elastic::IndexSetting[index_name].number_of_replicas } - } - ) - - mappings dynamic: 'strict' do - indexes :type, type: :keyword - - indexes :id, type: :integer - indexes :iid, type: :integer - - indexes :title, type: :text, index_options: 'positions', analyzer: :title_analyzer - indexes :description, type: :text, index_options: 'positions', analyzer: :code_analyzer - indexes :created_at, type: :date - indexes :updated_at, type: :date - indexes :state, type: :keyword - indexes :project_id, type: :integer - indexes :author_id, type: :integer - indexes :confidential, type: :boolean - indexes :hidden, type: :boolean - indexes :archived, type: :boolean - indexes :assignee_id, type: :integer - - indexes :visibility_level, type: :integer - indexes :issues_access_level, type: :integer - indexes :upvotes, type: :integer - indexes :namespace_ancestry_ids, type: :keyword - indexes :label_ids, type: :keyword - indexes :hashed_root_namespace_id, type: :integer - indexes :work_item_type_id, type: :integer - indexes :routing, type: :keyword - - indexes :schema_version, type: :short - end - end - end -end diff --git a/ee/lib/elastic/multi_version_class_proxy.rb b/ee/lib/elastic/multi_version_class_proxy.rb index a591eab2c6a48c..5dcedcaba4f628 100644 --- a/ee/lib/elastic/multi_version_class_proxy.rb +++ b/ee/lib/elastic/multi_version_class_proxy.rb @@ -25,9 +25,5 @@ def version(version) def proxy_class_name "#{@data_class.name}ClassProxy" end - - def fallback_proxy_class_name - :ApplicationClassProxy - end end end diff --git a/ee/lib/elastic/multi_version_instance_proxy.rb b/ee/lib/elastic/multi_version_instance_proxy.rb index de12e14bd29d0c..5758a57760eb60 100644 --- a/ee/lib/elastic/multi_version_instance_proxy.rb +++ b/ee/lib/elastic/multi_version_instance_proxy.rb @@ -18,9 +18,5 @@ def initialize(data_target, use_separate_indices: false) def proxy_class_name "#{@data_class.name}InstanceProxy" end - - def fallback_proxy_class_name - :ApplicationInstanceProxy - end end end diff --git a/ee/lib/elastic/multi_version_util.rb b/ee/lib/elastic/multi_version_util.rb index e29e5c18480150..6fe9bfd8faec9e 100644 --- a/ee/lib/elastic/multi_version_util.rb +++ b/ee/lib/elastic/multi_version_util.rb @@ -13,11 +13,10 @@ module MultiVersionUtil # @params version [String, Module] can be a string "V12p1" or module (Elastic::V12p1) def version(version) version = Elastic.const_get(version, false) if version.is_a?(String) - proxy_class = if version.const_defined?(proxy_class_name, false) version.const_get(proxy_class_name, false) else - version.const_get(fallback_proxy_class_name, false) + version.const_get(:ApplicationClassProxy, false) end proxy_class.new(data_target, use_separate_indices: use_separate_indices) diff --git a/ee/lib/gitlab/elastic/document_reference.rb b/ee/lib/gitlab/elastic/document_reference.rb index 0cd3955ad96b38..469d2227e5544f 100644 --- a/ee/lib/gitlab/elastic/document_reference.rb +++ b/ee/lib/gitlab/elastic/document_reference.rb @@ -145,7 +145,7 @@ def klass_proxy private def index_operation - return :upsert if klass == Issue + return :upsert if [Issue, Epic, WorkItem].include?(klass) :index end diff --git a/ee/lib/gitlab/elastic/helper.rb b/ee/lib/gitlab/elastic/helper.rb index 96ad686c2149cc..7ad6a6b509e270 100644 --- a/ee/lib/gitlab/elastic/helper.rb +++ b/ee/lib/gitlab/elastic/helper.rb @@ -4,11 +4,9 @@ module Gitlab module Elastic class Helper ES_SEPARATE_CLASSES = [ - Issue, Note, MergeRequest, Commit, - Epic, User, Wiki, Project, diff --git a/ee/lib/search/elastic/references/work_item.rb b/ee/lib/search/elastic/references/work_item.rb index a44a3e852d4fc3..6c165d62ff70bc 100644 --- a/ee/lib/search/elastic/references/work_item.rb +++ b/ee/lib/search/elastic/references/work_item.rb @@ -62,6 +62,8 @@ class WorkItem < Reference any_health_status ].freeze + DOC_TYPE = 'work_item' + override :serialize def self.serialize(record) new(record.id, record.es_parent).serialize -- GitLab From 8e0c9da96adbb7112126e546e964148ff316d5cd Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Tue, 21 Oct 2025 19:48:04 +0530 Subject: [PATCH 09/13] Fix failing specs --- .../search/rake_task_executor_service.rb | 19 ---- ...0152447_add_work_item_type_id_to_issues.rb | 21 ----- ee/lib/search/elastic/references/embedding.rb | 3 +- ee/spec/features/admin/admin_settings_spec.rb | 4 - ee/spec/lib/ee/gitlab/elastic/helper_spec.rb | 4 +- .../lib/elastic/latest/epic_config_spec.rb | 22 ----- .../lib/elastic/latest/issue_config_spec.rb | 32 ------- .../elastic/references/embedding_spec.rb | 27 +++--- .../cluster_reindexing_service_spec.rb | 36 ++++---- .../search/rake_task_executor_service_spec.rb | 90 ++++--------------- 10 files changed, 47 insertions(+), 211 deletions(-) delete mode 100644 ee/elastic/migrate/20231130152447_add_work_item_type_id_to_issues.rb delete mode 100644 ee/spec/lib/elastic/latest/epic_config_spec.rb delete mode 100644 ee/spec/lib/elastic/latest/issue_config_spec.rb diff --git a/ee/app/services/search/rake_task_executor_service.rb b/ee/app/services/search/rake_task_executor_service.rb index 97ef476fae5245..11774e0cfd0dab 100644 --- a/ee/app/services/search/rake_task_executor_service.rb +++ b/ee/app/services/search/rake_task_executor_service.rb @@ -14,7 +14,6 @@ class RakeTaskExecutorService estimate_cluster_size estimate_shard_sizes index_and_search_validation - index_epics index_work_items index_group_entities index_group_wikis @@ -386,28 +385,10 @@ def index_projects logger.info(" #{marker} (#{count})") end - def index_epics - logger.info('Indexing epics...') - - groups = if ::Gitlab::CurrentSettings.elasticsearch_limit_indexing? - ::Gitlab::CurrentSettings.elasticsearch_limited_namespaces.group_namespaces - else - Group.all - end - - groups.each_batch do |batch| - ::Elastic::ProcessInitialBookkeepingService.maintain_indexed_namespace_associations!(*batch, - associations_to_index: [:epics]) - end - - logger.info("Indexing epics... #{Rainbow('done').green}") - end - def index_group_entities raise 'This task cannot be run on GitLab.com' if ::Gitlab::Saas.feature_available?(:advanced_search) logger.info('Enqueuing Group level entities…') - index_epics index_work_items index_group_wikis end diff --git a/ee/elastic/migrate/20231130152447_add_work_item_type_id_to_issues.rb b/ee/elastic/migrate/20231130152447_add_work_item_type_id_to_issues.rb deleted file mode 100644 index 2dc558cce006d3..00000000000000 --- a/ee/elastic/migrate/20231130152447_add_work_item_type_id_to_issues.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -class AddWorkItemTypeIdToIssues < Elastic::Migration - include ::Search::Elastic::MigrationUpdateMappingsHelper - - private - - def index_name - ::Elastic::Latest::IssueConfig.index_name - end - - def new_mappings - { - work_item_type_id: { - type: 'integer' - } - } - end -end - -AddWorkItemTypeIdToIssues.prepend ::Search::Elastic::MigrationObsolete diff --git a/ee/lib/search/elastic/references/embedding.rb b/ee/lib/search/elastic/references/embedding.rb index 105eddf95c0ca7..d4e6ca94b32536 100644 --- a/ee/lib/search/elastic/references/embedding.rb +++ b/ee/lib/search/elastic/references/embedding.rb @@ -20,7 +20,8 @@ def self.serialize(record) end def self.ref(record) - new(record.class, record.id, record.es_parent) + klass = record.instance_of?(::Issue) ? ::WorkItem : record.class + new(klass, record.id, record.es_parent) end override :instantiate diff --git a/ee/spec/features/admin/admin_settings_spec.rb b/ee/spec/features/admin/admin_settings_spec.rb index 2e484f078bb02c..0c0d0b694faffc 100644 --- a/ee/spec/features/admin/admin_settings_spec.rb +++ b/ee/spec/features/admin/admin_settings_spec.rb @@ -83,8 +83,6 @@ fill_in 'application_setting_elasticsearch_shards[gitlab-test]', with: '120' fill_in 'application_setting_elasticsearch_replicas[gitlab-test]', with: '2' - fill_in 'application_setting_elasticsearch_shards[gitlab-test-issues]', with: '10' - fill_in 'application_setting_elasticsearch_replicas[gitlab-test-issues]', with: '3' fill_in 'application_setting_elasticsearch_shards[gitlab-test-notes]', with: '20' fill_in 'application_setting_elasticsearch_replicas[gitlab-test-notes]', with: '4' fill_in 'application_setting_elasticsearch_shards[gitlab-test-merge_requests]', with: '15' @@ -109,8 +107,6 @@ expect(current_settings.elasticsearch_replicas).to eq(2) expect(Elastic::IndexSetting['gitlab-test'].number_of_shards).to eq(120) expect(Elastic::IndexSetting['gitlab-test'].number_of_replicas).to eq(2) - expect(Elastic::IndexSetting['gitlab-test-issues'].number_of_shards).to eq(10) - expect(Elastic::IndexSetting['gitlab-test-issues'].number_of_replicas).to eq(3) expect(Elastic::IndexSetting['gitlab-test-notes'].number_of_shards).to eq(20) expect(Elastic::IndexSetting['gitlab-test-notes'].number_of_replicas).to eq(4) expect(Elastic::IndexSetting['gitlab-test-merge_requests'].number_of_shards).to eq(15) diff --git a/ee/spec/lib/ee/gitlab/elastic/helper_spec.rb b/ee/spec/lib/ee/gitlab/elastic/helper_spec.rb index 1185e5b48867c4..5f7f355d684221 100644 --- a/ee/spec/lib/ee/gitlab/elastic/helper_spec.rb +++ b/ee/spec/lib/ee/gitlab/elastic/helper_spec.rb @@ -568,7 +568,7 @@ end context 'when target_classes is provided' do - let(:target_classes) { [Issue] } + let(:target_classes) { [WorkItem] } it 'creates proxies for only the target classes' do expect(standalone_indices_proxies.count).to eq(1) @@ -906,7 +906,7 @@ end context 'when index_name is provided' do - let(:index_name) { 'gitlab-test-issues' } + let(:index_name) { 'gitlab-test-work_items' } it 'refreshes a single index' do expect(helper.client.indices).to receive(:refresh).with(index: index_name) diff --git a/ee/spec/lib/elastic/latest/epic_config_spec.rb b/ee/spec/lib/elastic/latest/epic_config_spec.rb deleted file mode 100644 index ac1c266a386a4a..00000000000000 --- a/ee/spec/lib/elastic/latest/epic_config_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' -require_relative './config_shared_examples' - -RSpec.describe Elastic::Latest::EpicConfig, feature_category: :global_search do - describe '.settings' do - it_behaves_like 'config settings return correct values' - end - - describe '.mappings' do - it 'returns config' do - expect(described_class.mapping).to be_a(Elasticsearch::Model::Indexing::Mappings) - end - end - - describe '.index_name' do - it 'includes' do - expect(described_class.index_name).to include('-epics') - end - end -end diff --git a/ee/spec/lib/elastic/latest/issue_config_spec.rb b/ee/spec/lib/elastic/latest/issue_config_spec.rb deleted file mode 100644 index 4b54b2fdd77f2c..00000000000000 --- a/ee/spec/lib/elastic/latest/issue_config_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' -require_relative './config_shared_examples' - -RSpec.describe Elastic::Latest::IssueConfig, feature_category: :global_search do - describe '.settings' do - it_behaves_like 'config settings return correct values' - end - - describe '.mappings' do - it 'returns config' do - expect(described_class.mapping).to be_a(Elasticsearch::Model::Indexing::Mappings) - end - end - - describe '.index_name' do - it 'uses the elasticsearch_prefix setting' do - allow(Gitlab::CurrentSettings).to receive(:elasticsearch_prefix).and_return('custom-prefix') - allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('test')) - - expect(described_class.index_name).to eq('custom-prefix-test-issues') - end - - it 'uses default prefix when setting returns default value' do - allow(Gitlab::CurrentSettings).to receive(:elasticsearch_prefix).and_return('gitlab') - allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development')) - - expect(described_class.index_name).to eq('gitlab-development-issues') - end - end -end diff --git a/ee/spec/lib/search/elastic/references/embedding_spec.rb b/ee/spec/lib/search/elastic/references/embedding_spec.rb index b7f0a46b648320..c2d60d1110d4ff 100644 --- a/ee/spec/lib/search/elastic/references/embedding_spec.rb +++ b/ee/spec/lib/search/elastic/references/embedding_spec.rb @@ -6,8 +6,8 @@ let_it_be(:project) { create(:project) } let_it_be(:issue) { create(:issue, project: project) } let(:routing) { issue.es_parent } - let(:embedding_ref) { described_class.new(Issue, issue.id, routing) } - let(:embedding_ref_serialized) { "Embedding|Issue|#{issue.id}|#{routing}" } + let(:embedding_ref) { described_class.new(WorkItem, issue.id, routing) } + let(:embedding_ref_serialized) { "Embedding|WorkItem|#{issue.id}|#{routing}" } let(:work_item_embedding_ref) { described_class.new(WorkItem, issue.id, routing) } before do @@ -29,7 +29,7 @@ ref = described_class.ref(issue) expect(ref).to be_an_instance_of(described_class) - expect(ref.model_klass).to eq(Issue) + expect(ref.model_klass).to eq(WorkItem) expect(ref.identifier).to eq(issue.id) expect(ref.routing).to eq(routing) end @@ -40,7 +40,7 @@ ref = described_class.instantiate(embedding_ref_serialized) expect(ref).to be_an_instance_of(described_class) - expect(ref.model_klass).to eq(Issue) + expect(ref.model_klass).to eq(WorkItem) expect(ref.identifier).to eq(issue.id) expect(ref.routing).to eq(routing) end @@ -50,7 +50,7 @@ let_it_be(:project2) { create(:project) } let_it_be(:issue2) { create(:issue, project: project2) } let(:embedding_ref2) { described_class.new(WorkItem, issue2.id, "project_#{project2.id}") } - let(:embedding_ref3) { described_class.new(Issue, issue2.id, "project_#{project2.id}") } + let(:embedding_ref3) { described_class.new(WorkItem, issue2.id, "project_#{project2.id}") } let(:embedding_ref4) { described_class.new(WorkItem, issue.id, "project_#{project.id}") } it 'preloads database records to avoid N+1 queries' do @@ -71,16 +71,15 @@ database_records = described_class.preload_indexing_data(refs).map(&:database_record) end.not_to exceed_query_limit(control) - expect(database_records[0]).to eq(issue) - expect(database_records[2]).to eq(issue2) + expect(database_records[0].id).to eq(issue.id) + expect(database_records[2].id).to eq(issue2.id) end it 'calls preload in batches not to overload the database' do stub_const('Search::Elastic::Concerns::DatabaseClassReference::BATCH_SIZE', 1) refs = [embedding_ref, embedding_ref2] - expect(Issue).to receive(:preload_indexing_data).and_call_original.once - expect(WorkItem).to receive(:preload_indexing_data).and_call_original.once + expect(WorkItem).to receive(:preload_indexing_data).and_call_original.twice described_class.preload_indexing_data(refs) end @@ -188,14 +187,8 @@ end describe '#index_name' do - it 'is equal to proxy index name' do - expect(embedding_ref.index_name).to eq('gitlab-test-issues') - end - - context 'if type class exists' do - it 'is equal type class index name' do - expect(work_item_embedding_ref.index_name).to eq('gitlab-test-work_items') - end + it 'is equal type class index name' do + expect(embedding_ref.index_name).to eq('gitlab-test-work_items') end end end diff --git a/ee/spec/services/search/elastic/cluster_reindexing_service_spec.rb b/ee/spec/services/search/elastic/cluster_reindexing_service_spec.rb index 65b6396b88759c..1d7da0576d8556 100644 --- a/ee/spec/services/search/elastic/cluster_reindexing_service_spec.rb +++ b/ee/spec/services/search/elastic/cluster_reindexing_service_spec.rb @@ -89,9 +89,9 @@ end context 'for state: indexing_paused' do - let(:issues_alias) { Issue.__elasticsearch__.index_name } - let(:issues_old_index_name) { "#{issues_alias}-1" } - let(:issues_new_index_name) { "#{issues_alias}-reindex" } + let(:notes_alias) { Note.__elasticsearch__.index_name } + let(:notes_old_index_name) { "#{notes_alias}-1" } + let(:notes_new_index_name) { "#{notes_alias}-reindex" } let(:main_alias) { Repository.__elasticsearch__.index_name } let(:main_old_index_name) { "#{main_alias}-1" } @@ -103,14 +103,14 @@ before do allow(helper).to receive(:target_index_names) { |options| { "#{options[:target]}-1" => true } } allow(helper).to receive_messages( - create_standalone_indices: { issues_new_index_name => issues_alias }, + create_standalone_indices: { notes_new_index_name => notes_alias }, create_empty_index: { main_new_index_name => main_alias } ) allow(helper).to receive(:reindex) { |options| "#{options[:to]}_task_id" } allow(helper).to receive(:get_settings) do |options| number_of_shards = case options[:index_name] when main_old_index_name then 10 - when issues_old_index_name then 3 + when notes_old_index_name then 1 else 1 end @@ -133,13 +133,13 @@ expect(slice_1.elastic_task).to eq("#{main_new_index_name}_task_id") expect(slice_1.elastic_slice).to eq(0) - subtask_2 = subtasks.find { |subtask| subtask.alias_name == issues_alias } + subtask_2 = subtasks.find { |subtask| subtask.alias_name == notes_alias } slice_2 = subtask_2.slices.last - expect(subtask_2.index_name_to).to eq(issues_new_index_name) - expect(subtask_2.slices.count).to eq(6) - expect(slice_2.elastic_max_slice).to eq(6) - expect(slice_2.elastic_task).to eq("#{issues_new_index_name}_task_id") - expect(slice_2.elastic_slice).to eq(5) + expect(subtask_2.index_name_to).to eq(notes_new_index_name) + expect(subtask_2.slices.count).to eq(2) + expect(slice_2.elastic_max_slice).to eq(2) + expect(slice_2.elastic_task).to eq("#{notes_new_index_name}_task_id") + expect(slice_2.elastic_slice).to eq(1) end end @@ -150,8 +150,8 @@ allow(helper).to receive(:target_index_names) { |options| { "#{options[:target]}-1" => true } } end - context 'when targets set to issue and repository' do - let(:targets) { %w[Issue Repository] } + context 'when targets set to note and repository' do + let(:targets) { %w[Note Repository] } it 'creates multiple indices' do expect(helper).to receive(:create_empty_index).and_return(main_new_index_name => main_alias) @@ -159,8 +159,8 @@ is_expected.to receive(:launch_subtasks).with( array_including( { - alias_name: issues_alias, - index_name_from: issues_old_index_name, + alias_name: notes_alias, + index_name_from: notes_old_index_name, index_name_to: anything }, { @@ -176,15 +176,15 @@ end context 'when targets do not include repository' do - let(:targets) { %w[Issue] } + let(:targets) { %w[Note] } it 'does not create the main index' do expect(helper).not_to receive(:create_empty_index) is_expected.to receive(:launch_subtasks).with( array_including( hash_including( - alias_name: issues_alias, - index_name_from: issues_old_index_name, + alias_name: notes_alias, + index_name_from: notes_old_index_name, index_name_to: anything ) )) diff --git a/ee/spec/services/search/rake_task_executor_service_spec.rb b/ee/spec/services/search/rake_task_executor_service_spec.rb index 024a3b7c6649fd..b23de294105f4e 100644 --- a/ee/spec/services/search/rake_task_executor_service_spec.rb +++ b/ee/spec/services/search/rake_task_executor_service_spec.rb @@ -256,7 +256,8 @@ end describe '#estimate_shard_sizes' do - let(:db_counts) { [400, 1500, 10_000_000, 50_000_000, 100_000_000, 4_000, 5_000, 5_000] } + # DB_CLASSES = [Note, MergeRequest, User, Project, WorkItem, Vulnerability] + let(:db_counts) { [400, 1500, 10_000_000, 4_000, 5_000, 6_000] } before do allow(logger).to receive(:info) @@ -269,46 +270,25 @@ end it 'outputs shard size estimates' do - expected_work_items = <<~ESTIMATE - - gitlab-test-work_items: - recommended shards: 5 - recommended replicas: 1 - document count: 5,000 - ESTIMATE - - expected_issues = <<~ESTIMATE - - gitlab-test-issues: - recommended shards: 5 - recommended replicas: 1 - document count: 400 - ESTIMATE - expected_notes = <<~ESTIMATE.chomp - gitlab-test-notes: recommended shards: 5 recommended replicas: 1 - document count: 1,500 + document count: 400 ESTIMATE expected_merge_requests = <<~ESTIMATE.chomp - gitlab-test-merge_requests: recommended shards: 5 recommended replicas: 1 - document count: 10,000,000 - ESTIMATE - - expected_epics = <<~ESTIMATE.chomp - - gitlab-test-epics: - recommended shards: 10 - recommended replicas: 1 - document count: 50,000,000 + document count: 1,500 ESTIMATE expected_users = <<~ESTIMATE.chomp - gitlab-test-users: - recommended shards: 20 + recommended shards: 5 recommended replicas: 1 - document count: 100,000,000 + document count: 10,000,000 ESTIMATE expected_projects = <<~ESTIMATE.chomp @@ -318,11 +298,18 @@ document count: 4,000 ESTIMATE + expected_work_items = <<~ESTIMATE.chomp + - gitlab-test-work_items: + recommended shards: 5 + recommended replicas: 1 + document count: 5,000 + ESTIMATE + expected_vulnerabilities = <<~ESTIMATE.chomp - gitlab-test-vulnerabilities: recommended shards: 5 recommended replicas: 1 - document count: 5,000 + document count: 6,000 ESTIMATE expected_main_index = <<~ESTIMATE.chomp @@ -343,10 +330,8 @@ recommended replicas: 1 ESTIMATE - expect(logger).to receive(:info).with(/#{expected_issues}/) expect(logger).to receive(:info).with(/#{expected_notes}/) expect(logger).to receive(:info).with(/#{expected_merge_requests}/) - expect(logger).to receive(:info).with(/#{expected_epics}/) expect(logger).to receive(:info).with(/#{expected_users}/) expect(logger).to receive(:info).with(/#{expected_projects}/) expect(logger).to receive(:info).with(/#{expected_work_items}/) @@ -714,51 +699,6 @@ end end - describe '#index_epics' do - let!(:epic) { create(:epic) } - - it 'calls maintain_indexed_namespace_associations for groups' do - expect(logger).to receive(:info).with(/Indexing epics/).twice - expect(Elastic::ProcessInitialBookkeepingService).to receive(:maintain_indexed_namespace_associations!) - .with(epic.group, associations_to_index: [:epics]) - - service.execute(:index_epics) - end - - it 'avoids N+1 queries', :use_sql_query_cache do - control = ActiveRecord::QueryRecorder.new(skip_cached: false) { service.execute(:index_epics) } - - create_list(:epic, 3) - - expect(Elastic::ProcessInitialBookkeepingService).to receive(:maintain_indexed_namespace_associations!) - - expect { service.execute(:index_epics) }.to issue_same_number_of_queries_as(control) - end - - context 'with limited indexing enabled' do - let!(:group1) { create(:group) } - let!(:group2) { create(:group) } - let!(:group3) { create(:group) } - - before do - create(:elasticsearch_indexed_namespace, namespace: group1) - create(:elasticsearch_indexed_namespace, namespace: group3) - - stub_ee_application_setting(elasticsearch_limit_indexing: true) - end - - it 'does not call maintain_indexed_namespace_associations for groups that should not be indexed' do - expect(logger).to receive(:info).with(/Indexing epics/).twice - expect(Elastic::ProcessBookkeepingService).to receive(:maintain_indexed_namespace_associations!) do |*params| - expect(params.count).to eq(3) - expect([params[0], params[1]]).to contain_exactly(group1, group3) - expect(params[2]).to eq(associations_to_index: [:epics]) - end - service.execute(:index_epics) - end - end - end - describe '#projects_not_indexed' do let_it_be(:project) { create(:project, :repository) } let_it_be(:project_no_repository) { create(:project) } @@ -898,7 +838,7 @@ end it 'calls other tasks in order' do - expect(service).to receive(:index_epics).ordered + expect(service).to receive(:index_work_items).ordered expect(service).to receive(:index_group_wikis).ordered index_group_entities -- GitLab From e84a5a5ae96f83c6a3bc660f5a080907bb9339c6 Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Tue, 21 Oct 2025 22:19:34 +0530 Subject: [PATCH 10/13] Remove related spec file --- ...20231130152447_add_work_item_type_id_to_issues_spec.rb | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 ee/spec/elastic/migrate/20231130152447_add_work_item_type_id_to_issues_spec.rb diff --git a/ee/spec/elastic/migrate/20231130152447_add_work_item_type_id_to_issues_spec.rb b/ee/spec/elastic/migrate/20231130152447_add_work_item_type_id_to_issues_spec.rb deleted file mode 100644 index 7f126c66858e6c..00000000000000 --- a/ee/spec/elastic/migrate/20231130152447_add_work_item_type_id_to_issues_spec.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' -require File.expand_path('ee/elastic/migrate/20231130152447_add_work_item_type_id_to_issues.rb') - -RSpec.describe AddWorkItemTypeIdToIssues, feature_category: :global_search do - it_behaves_like 'a deprecated Advanced Search migration', 20231130152447 -end -- GitLab From dbbdcf597a985db66bfeeb862ff48f09e65f88e5 Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 22 Oct 2025 16:12:22 +0530 Subject: [PATCH 11/13] Add index_work_items and index_namespaces tasks, remove index_epics task --- doc/integration/advanced_search/elasticsearch.md | 13 ++++++------- ee/lib/tasks/gitlab/elastic.rake | 11 ++++++++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/doc/integration/advanced_search/elasticsearch.md b/doc/integration/advanced_search/elasticsearch.md index bd9852e7deb385..f1c15711805177 100644 --- a/doc/integration/advanced_search/elasticsearch.md +++ b/doc/integration/advanced_search/elasticsearch.md @@ -496,7 +496,6 @@ To index specific data, use the following Rake tasks: ```shell # For installations that use the Linux package -sudo gitlab-rake gitlab:elastic:index_epics sudo gitlab-rake gitlab:elastic:index_work_items sudo gitlab-rake gitlab:elastic:index_group_wikis sudo gitlab-rake gitlab:elastic:index_namespaces @@ -505,7 +504,6 @@ sudo gitlab-rake gitlab:elastic:index_snippets sudo gitlab-rake gitlab:elastic:index_users # For self-compiled installations -bundle exec rake gitlab:elastic:index_epics RAILS_ENV=production bundle exec rake gitlab:elastic:index_work_items RAILS_ENV=production bundle exec rake gitlab:elastic:index_group_wikis RAILS_ENV=production bundle exec rake gitlab:elastic:index_namespaces RAILS_ENV=production @@ -1002,8 +1000,9 @@ The following are some available Rake tasks: | [`sudo gitlab-rake gitlab:elastic:resume_indexing`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Resumes indexing for advanced search. | | [`sudo gitlab-rake gitlab:elastic:index_and_search_validation`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Validates cluster connectivity, index, and search operations for all indices. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/200664) in GitLab 18.3. | | [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Iterates over all projects, and queues Sidekiq jobs to index them in the background. It can only be used after the index is created. | -| [`sudo gitlab-rake gitlab:elastic:index_group_entities`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Invokes `gitlab:elastic:index_epics` and `gitlab:elastic:index_group_wikis`. | -| [`sudo gitlab-rake gitlab:elastic:index_epics`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Indexes all epics from the groups where Elasticsearch is enabled. | +| [`sudo gitlab-rake gitlab:elastic:index_group_entities`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Invokes `gitlab:elastic:index_work_items` and `gitlab:elastic:index_group_wikis`. | +| [`sudo gitlab-rake gitlab:elastic:index_work_items`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Indexes all work items from the groups where Elasticsearch is enabled. | +| [`sudo gitlab-rake gitlab:elastic:index_namespaces`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Indexes all root namespaces. | | [`sudo gitlab-rake gitlab:elastic:index_group_wikis`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Indexes all wikis from the groups where Elasticsearch is enabled. | | [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Determines the overall indexing status of all project repository data (code, commits, and wikis). The status is calculated by dividing the number of indexed projects by the total number of projects and multiplying by 100. This task does not include non-repository data such as issues, merge requests, or milestones. | | [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. This command results in a complete wipe of the index, and it should be used with caution. | @@ -1245,17 +1244,17 @@ due to large volumes of data being indexed: indexer to "forget" all progress, so it retries the indexing process from the start. -1. Epics, group wikis, personal snippets, and users are not associated with a project and must be indexed separately: +1. Work items, group wikis, personal snippets, and users are not associated with a project and must be indexed separately: ```shell # For installations that use the Linux package - sudo gitlab-rake gitlab:elastic:index_epics + sudo gitlab-rake gitlab:elastic:index_work_items sudo gitlab-rake gitlab:elastic:index_group_wikis sudo gitlab-rake gitlab:elastic:index_snippets sudo gitlab-rake gitlab:elastic:index_users # For self-compiled installations - bundle exec rake gitlab:elastic:index_epics RAILS_ENV=production + bundle exec rake gitlab:elastic:index_work_items RAILS_ENV=production bundle exec rake gitlab:elastic:index_group_wikis RAILS_ENV=production bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production bundle exec rake gitlab:elastic:index_users RAILS_ENV=production diff --git a/ee/lib/tasks/gitlab/elastic.rake b/ee/lib/tasks/gitlab/elastic.rake index a1605ab2dc344d..9c17b3156ed703 100644 --- a/ee/lib/tasks/gitlab/elastic.rake +++ b/ee/lib/tasks/gitlab/elastic.rake @@ -67,9 +67,14 @@ namespace :gitlab do Search::RakeTask::Elastic.task_executor_service.execute(:index_users) end - desc 'GitLab | Elasticsearch | Index epics' - task index_epics: :environment do - Search::RakeTask::Elastic.task_executor_service.execute(:index_epics) + desc 'GitLab | Elasticsearch | Index work items' + task index_work_items: :environment do + Search::RakeTask::Elastic.task_executor_service.execute(:index_work_items) + end + + desc 'GitLab | Elasticsearch | Index namespaces' + task index_namespaces: :environment do + Search::RakeTask::Elastic.task_executor_service.execute(:index_namespaces) end desc 'GitLab | Elasticsearch | Index group wikis' -- GitLab From f2bc0b412e22784db407104535c0bf02bed5691f Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 22 Oct 2025 16:14:49 +0530 Subject: [PATCH 12/13] Add all rake tasks in the documentation --- doc/integration/advanced_search/elasticsearch.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/integration/advanced_search/elasticsearch.md b/doc/integration/advanced_search/elasticsearch.md index f1c15711805177..a325577aebdda8 100644 --- a/doc/integration/advanced_search/elasticsearch.md +++ b/doc/integration/advanced_search/elasticsearch.md @@ -1004,13 +1004,14 @@ The following are some available Rake tasks: | [`sudo gitlab-rake gitlab:elastic:index_work_items`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Indexes all work items from the groups where Elasticsearch is enabled. | | [`sudo gitlab-rake gitlab:elastic:index_namespaces`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Indexes all root namespaces. | | [`sudo gitlab-rake gitlab:elastic:index_group_wikis`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Indexes all wikis from the groups where Elasticsearch is enabled. | +| [`sudo gitlab-rake gitlab:elastic:index_snippets`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Performs an Elasticsearch import that indexes the snippets data. | +| [`sudo gitlab-rake gitlab:elastic:index_users`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Imports all users into Elasticsearch. | +| [`sudo gitlab-rake gitlab:elastic:index_vulnerabilities`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Indexes all vulnerabilities. | | [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Determines the overall indexing status of all project repository data (code, commits, and wikis). The status is calculated by dividing the number of indexed projects by the total number of projects and multiplying by 100. This task does not include non-repository data such as issues, merge requests, or milestones. | | [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. This command results in a complete wipe of the index, and it should be used with caution. | | [`sudo gitlab-rake gitlab:elastic:create_empty_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Generates empty indices (the default index and a separate issues index) and assigns an alias for each on the Elasticsearch side only if it doesn't already exist. | | [`sudo gitlab-rake gitlab:elastic:delete_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Removes the GitLab indices and aliases (if they exist) on the Elasticsearch instance. | | [`sudo gitlab-rake gitlab:elastic:recreate_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Wrapper task for `gitlab:elastic:delete_index` and `gitlab:elastic:create_empty_index`. Does not queue any indexing jobs. | -| [`sudo gitlab-rake gitlab:elastic:index_snippets`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Performs an Elasticsearch import that indexes the snippets data. | -| [`sudo gitlab-rake gitlab:elastic:index_users`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Imports all users into Elasticsearch. | | [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Displays which projects do not have repository data indexed. This task does not include non-repository data such as issues, merge requests, or milestones. | | [`sudo gitlab-rake gitlab:elastic:reindex_cluster`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Schedules a zero-downtime cluster reindexing task. | | [`sudo gitlab-rake gitlab:elastic:mark_reindex_failed`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Mark the most recent reindex job as failed. | -- GitLab From e7d7dcf928faf91d0e691ffe93501332bb8649d4 Mon Sep 17 00:00:00 2001 From: Siddharth Dungarwal Date: Wed, 22 Oct 2025 18:48:00 +0530 Subject: [PATCH 13/13] Fix failing spec --- ee/spec/tasks/gitlab/elastic_rake_spec.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ee/spec/tasks/gitlab/elastic_rake_spec.rb b/ee/spec/tasks/gitlab/elastic_rake_spec.rb index ef41ee2d363b08..337639032ca2e6 100644 --- a/ee/spec/tasks/gitlab/elastic_rake_spec.rb +++ b/ee/spec/tasks/gitlab/elastic_rake_spec.rb @@ -49,8 +49,12 @@ include_examples 'rake task executor task', :index_users end - describe 'gitlab:elastic:index_epics' do - include_examples 'rake task executor task', :index_epics + describe 'gitlab:elastic:index_work_items' do + include_examples 'rake task executor task', :index_work_items + end + + describe 'gitlab:elastic:index_namespaces' do + include_examples 'rake task executor task', :index_namespaces end describe 'gitlab:elastic:index_group_wikis' do -- GitLab