Commit f69bcd39 authored by Kerri Miller's avatar Kerri Miller

Merge branch...

Merge branch '324745-remove-more-n-plus-1-queries-for-indexing-notes-in-elasticsearch' into 'master'

Fix more N+1 issues when indexing notes in Elasticsearch

See merge request gitlab-org/gitlab!58751
parents 9139c233 f1f55e6e
---
title: Fix more N+1 issues when indexing notes in Elasticsearch
merge_request: 58751
author:
type: performance
...@@ -26,7 +26,7 @@ module Elastic ...@@ -26,7 +26,7 @@ module Elastic
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def preload_indexing_data(relation) def preload_indexing_data(relation)
relation.includes(noteable: :assignees) relation.includes(noteable: :assignees, project: [:project_feature, :route])
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_state do RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_state, :elastic do
let(:ref_class) { ::Gitlab::Elastic::DocumentReference } let(:ref_class) { ::Gitlab::Elastic::DocumentReference }
let(:fake_refs) { Array.new(10) { |i| ref_class.new(Issue, i, "issue_#{i}", 'project_1') } } let(:fake_refs) { Array.new(10) { |i| ref_class.new(Issue, i, "issue_#{i}", 'project_1') } }
...@@ -125,17 +125,11 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st ...@@ -125,17 +125,11 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st
end end
describe '#execute' do describe '#execute' do
let(:shard_limit) { 5 }
let(:shard_number) { 2 }
let(:limit) { shard_limit * shard_number }
before do
stub_const('Elastic::ProcessBookkeepingService::SHARD_LIMIT', shard_limit)
stub_const('Elastic::ProcessBookkeepingService::SHARDS_NUMBER', shard_number)
end
context 'limit is less than refs count' do context 'limit is less than refs count' do
let(:shard_limit) { 2 } before do
stub_const('Elastic::ProcessBookkeepingService::SHARD_LIMIT', 2)
stub_const('Elastic::ProcessBookkeepingService::SHARDS_NUMBER', 2)
end
it 'processes only up to limit' do it 'processes only up to limit' do
described_class.track!(*fake_refs) described_class.track!(*fake_refs)
...@@ -143,7 +137,7 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st ...@@ -143,7 +137,7 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st
expect(described_class.queue_size).to eq(fake_refs.size) expect(described_class.queue_size).to eq(fake_refs.size)
allow_processing(*fake_refs) allow_processing(*fake_refs)
expect { described_class.new.execute }.to change(described_class, :queue_size).by(-limit) expect { described_class.new.execute }.to change(described_class, :queue_size).by(-4)
end end
end end
...@@ -151,17 +145,17 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st ...@@ -151,17 +145,17 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st
described_class.track!(*fake_refs) described_class.track!(*fake_refs)
expect(described_class.queue_size).to eq(fake_refs.size) expect(described_class.queue_size).to eq(fake_refs.size)
expect_processing(*fake_refs[0...limit]) expect_processing(*fake_refs)
expect { described_class.new.execute }.to change(described_class, :queue_size).by(-limit) expect { described_class.new.execute }.to change(described_class, :queue_size).by(-fake_refs.count)
end end
it 'returns the number of documents processed' do it 'returns the number of documents processed' do
described_class.track!(*fake_refs) described_class.track!(*fake_refs)
expect_processing(*fake_refs[0...limit]) expect_processing(*fake_refs)
expect(described_class.new.execute).to eq(limit) expect(described_class.new.execute).to eq(fake_refs.count)
end end
it 'returns 0 without writing to the index when there are no documents' do it 'returns 0 without writing to the index when there are no documents' do
...@@ -175,9 +169,9 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st ...@@ -175,9 +169,9 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st
failed = fake_refs[0] failed = fake_refs[0]
expect(described_class.queue_size).to eq(10) expect(described_class.queue_size).to eq(10)
expect_processing(*fake_refs[0...limit], failures: [failed]) expect_processing(*fake_refs, failures: [failed])
expect { described_class.new.execute }.to change(described_class, :queue_size).by(-limit + 1) expect { described_class.new.execute }.to change(described_class, :queue_size).by(-fake_refs.count + 1)
shard = described_class.shard_number(failed.serialize) shard = described_class.shard_number(failed.serialize)
serialized = described_class.queued_items[shard].first[0] serialized = described_class.queued_items[shard].first[0]
...@@ -224,29 +218,37 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st ...@@ -224,29 +218,37 @@ RSpec.describe Elastic::ProcessBookkeepingService, :clean_gitlab_redis_shared_st
end end
it 'does not have N+1 queries for notes' do it 'does not have N+1 queries for notes' do
notes = [] # Gitaly N+1 calls when processing notes on commits
# https://gitlab.com/gitlab-org/gitlab/-/issues/327086 . Even though
2.times do # this block is in the spec there is still an N+1 to fix in the actual
notes << create(:note) # code.
notes << create(:discussion_note_on_merge_request) Gitlab::GitalyClient.allow_n_plus_1_calls do
notes << create(:note_on_merge_request) notes = []
notes << create(:note_on_commit)
2.times do
notes << create(:note)
notes << create(:discussion_note_on_merge_request)
notes << create(:note_on_merge_request)
notes << create(:note_on_commit)
notes << create(:diff_note_on_merge_request)
end
described_class.track!(*notes)
control = ActiveRecord::QueryRecorder.new(skip_cached: false) { described_class.new.execute }
3.times do
notes << create(:note)
notes << create(:discussion_note_on_merge_request)
notes << create(:note_on_merge_request)
notes << create(:note_on_commit)
notes << create(:diff_note_on_merge_request)
end
described_class.track!(*notes)
expect { described_class.new.execute }.not_to exceed_all_query_limit(control)
end end
described_class.track!(*notes)
control = ActiveRecord::QueryRecorder.new(skip_cached: false) { described_class.new.execute }
3.times do
notes << create(:note)
notes << create(:discussion_note_on_merge_request)
notes << create(:note_on_merge_request)
notes << create(:note_on_commit)
end
described_class.track!(*notes)
expect { described_class.new.execute }.not_to exceed_all_query_limit(control)
end end
it 'does not have N+1 queries for issues' do it 'does not have N+1 queries for issues' 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