Commit 7b187003 authored by Dmitry Gruzd's avatar Dmitry Gruzd

Fix AddUpvotesToMergeRequests migration

EE: true
Changelog: fixed
parent f5bf00dc
...@@ -5,14 +5,6 @@ module Elastic ...@@ -5,14 +5,6 @@ module Elastic
UPDATE_BATCH_SIZE = 100 UPDATE_BATCH_SIZE = 100
def migrate def migrate
# only create mappings on the first run
if respond_to?(:new_mappings) && migration_state[:update_mappings].blank?
update_mapping!(index_name, { properties: new_mappings })
options = { update_mappings: true }
set_migration_state(options)
end
if completed? if completed?
log "Skipping adding #{field_name} field to #{index_name} documents migration since it is already applied" log "Skipping adding #{field_name} field to #{index_name} documents migration since it is already applied"
return return
...@@ -109,9 +101,5 @@ module Elastic ...@@ -109,9 +101,5 @@ module Elastic
UPDATE_BATCH_SIZE UPDATE_BATCH_SIZE
end end
def update_mapping!(index_name, mappings)
helper.update_mapping(index_name: index_name, mappings: mappings)
end
end end
end end
# frozen_string_literal: true
module Elastic
module MigrationUpdateMappingsHelper
def migrate
if completed?
log "Skipping updating #{index_name} mapping migration since it is already applied"
return
end
log "Adding #{new_mappings.inspect} to #{index_name} mapping"
update_mapping!(index_name, { properties: new_mappings })
end
def completed?
helper.refresh_index(index_name: index_name)
mappings = helper.get_mapping(index_name: index_name)
# Check if mappings include all new_mappings
new_mappings.keys.map(&:to_s).to_set.subset?(mappings.keys.to_set)
end
private
def index_name
raise NotImplementedError
end
def new_mappings
raise NotImplementedError
end
def update_mapping!(index_name, mappings)
helper.update_mapping(index_name: index_name, mappings: mappings)
end
end
end
# frozen_string_literal: true
class AddUpvotesMappingsToMergeRequests < Elastic::Migration
include Elastic::MigrationUpdateMappingsHelper
DOCUMENT_TYPE = MergeRequest
private
def index_name
DOCUMENT_TYPE.__elasticsearch__.index_name
end
def new_mappings
{ upvotes: { type: 'integer' } }
end
end
...@@ -9,10 +9,6 @@ class AddUpvotesToMergeRequests < Elastic::Migration ...@@ -9,10 +9,6 @@ class AddUpvotesToMergeRequests < Elastic::Migration
DOCUMENT_TYPE = MergeRequest DOCUMENT_TYPE = MergeRequest
def new_mappings
{ upvotes: { type: 'integer' } }
end
private private
def index_name def index_name
......
# frozen_string_literal: true # frozen_string_literal: true
class AddNamespaceAncestryToIssuesMapping < Elastic::Migration class AddNamespaceAncestryToIssuesMapping < Elastic::Migration
include Elastic::MigrationBackfillHelper include Elastic::MigrationUpdateMappingsHelper
DOCUMENT_KLASS = Issue DOCUMENT_KLASS = Issue
......
...@@ -29,7 +29,7 @@ module Elastic ...@@ -29,7 +29,7 @@ module Elastic
data['visibility_level'] = target.project.visibility_level data['visibility_level'] = target.project.visibility_level
data['merge_requests_access_level'] = safely_read_project_feature_for_elasticsearch(:merge_requests) data['merge_requests_access_level'] = safely_read_project_feature_for_elasticsearch(:merge_requests)
data['upvotes'] = target.lazy_upvotes_count data['upvotes'] = target.lazy_upvotes_count if Elastic::DataMigrationService.migration_has_finished?(:add_upvotes_mappings_to_merge_requests)
data.merge(generic_attributes) data.merge(generic_attributes)
end end
......
# frozen_string_literal: true
require 'spec_helper'
require File.expand_path('ee/elastic/migrate/20210722112500_add_upvotes_mappings_to_merge_requests.rb')
RSpec.describe AddUpvotesMappingsToMergeRequests, :elastic, :sidekiq_inline do
let(:version) { 20210722112500 }
let(:migration) { described_class.new(version) }
let(:helper) { Gitlab::Elastic::Helper.new }
before do
allow(migration).to receive(:helper).and_return(helper)
end
describe '.migrate' do
subject { migration.migrate }
context 'when migration is already completed' do
it 'does not modify data' do
expect(helper).not_to receive(:update_mapping)
subject
end
end
context 'migration process' do
before do
allow(helper).to receive(:get_mapping).and_return({})
end
it 'updates the issues index mappings' do
expect(helper).to receive(:update_mapping)
subject
end
end
end
describe '.completed?' do
context 'mapping has been updated' do
specify { expect(migration).to be_completed }
end
context 'mapping has not been updated' do
before do
allow(helper).to receive(:get_mapping).and_return({})
end
specify { expect(migration).not_to be_completed }
end
end
end
...@@ -73,25 +73,6 @@ RSpec.describe AddUpvotesToMergeRequests, :elastic, :sidekiq_inline do ...@@ -73,25 +73,6 @@ RSpec.describe AddUpvotesToMergeRequests, :elastic, :sidekiq_inline do
migration.migrate migration.migrate
end end
it 'only updates mappings on the first run' do
helper = Gitlab::Elastic::Helper.new
allow(Gitlab::Elastic::Helper).to receive(:default).and_return(helper)
allow(migration).to receive(:batch_size).and_return(2)
expect(helper).to receive(:update_mapping).and_call_original
# cannot use subject in spec because it is memoized
migration.migrate
ensure_elasticsearch_index!
expect(migration.migration_state).to include(update_mappings: true)
expect(helper).not_to receive(:update_mapping)
migration.migrate
end
end end
end end
......
...@@ -69,35 +69,55 @@ RSpec.describe MergeRequest, :elastic do ...@@ -69,35 +69,55 @@ RSpec.describe MergeRequest, :elastic do
expect(results.first.title).to eq('bla-bla merge request') expect(results.first.title).to eq('bla-bla merge request')
end end
it "returns json with all needed elements" do shared_examples 'merge request json fields' do |remove_fields|
merge_request = create :merge_request it "returns json with all needed elements" do
merge_request.project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) merge_request = create :merge_request
create(:award_emoji, :upvote, awardable: merge_request) merge_request.project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
create(:award_emoji, :upvote, awardable: merge_request)
expected_hash = merge_request.attributes.extract!(
'id', expected_hash = merge_request.attributes.extract!(
'iid', 'id',
'target_branch', 'iid',
'source_branch', 'target_branch',
'title', 'source_branch',
'description', 'title',
'created_at', 'description',
'updated_at', 'created_at',
'state', 'updated_at',
'merge_status', 'state',
'source_project_id', 'merge_status',
'target_project_id', 'source_project_id',
'author_id' 'target_project_id',
).merge({ 'author_id'
'state' => merge_request.state, ).merge({
'type' => merge_request.es_type, 'state' => merge_request.state,
'merge_requests_access_level' => ProjectFeature::ENABLED, 'type' => merge_request.es_type,
'visibility_level' => Gitlab::VisibilityLevel::INTERNAL, 'merge_requests_access_level' => ProjectFeature::ENABLED,
'project_id' => merge_request.target_project.id, 'visibility_level' => Gitlab::VisibilityLevel::INTERNAL,
'upvotes' => 1 'project_id' => merge_request.target_project.id,
}) 'upvotes' => 1
})
expect(merge_request.__elasticsearch__.as_indexed_json).to eq(expected_hash)
expected_hash = expected_hash.except(*remove_fields.map(&:to_s))
expect(merge_request.__elasticsearch__.as_indexed_json).to eq(expected_hash)
end
end
context 'add_upvotes_mappings_to_merge_requests is not completed' do
before do
set_elasticsearch_migration_to(:add_upvotes_mappings_to_merge_requests, including: false)
end
include_context 'merge request json fields', [:upvotes]
end
context 'add_upvotes_mappings_to_merge_requests is completed' do
before do
set_elasticsearch_migration_to(:add_upvotes_mappings_to_merge_requests, including: true)
end
include_context 'merge request json fields', []
end end
it 'handles when a project is missing project_feature' do it 'handles when a project is missing project_feature' do
......
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