Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-04-20 13:00:54 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-04-20 13:00:54 +0300
commit3cccd102ba543e02725d247893729e5c73b38295 (patch)
treef36a04ec38517f5deaaacb5acc7d949688d1e187 /spec/services/database/consistency_check_service_spec.rb
parent205943281328046ef7b4528031b90fbda70c75ac (diff)
Add latest changes from gitlab-org/gitlab@14-10-stable-eev14.10.0-rc42
Diffstat (limited to 'spec/services/database/consistency_check_service_spec.rb')
-rw-r--r--spec/services/database/consistency_check_service_spec.rb154
1 files changed, 154 insertions, 0 deletions
diff --git a/spec/services/database/consistency_check_service_spec.rb b/spec/services/database/consistency_check_service_spec.rb
new file mode 100644
index 00000000000..2e642451432
--- /dev/null
+++ b/spec/services/database/consistency_check_service_spec.rb
@@ -0,0 +1,154 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Database::ConsistencyCheckService do
+ let(:batch_size) { 5 }
+ let(:max_batches) { 2 }
+
+ before do
+ stub_const("Gitlab::Database::ConsistencyChecker::BATCH_SIZE", batch_size)
+ stub_const("Gitlab::Database::ConsistencyChecker::MAX_BATCHES", max_batches)
+ end
+
+ after do
+ redis_shared_state_cleanup!
+ end
+
+ subject(:consistency_check_service) do
+ described_class.new(
+ source_model: Namespace,
+ target_model: Ci::NamespaceMirror,
+ source_columns: %w[id traversal_ids],
+ target_columns: %w[namespace_id traversal_ids]
+ )
+ end
+
+ describe '#random_start_id' do
+ let(:batch_size) { 5 }
+
+ before do
+ create_list(:namespace, 50) # This will also create Ci::NameSpaceMirror objects
+ end
+
+ it 'generates a random start_id within the records ids' do
+ 10.times do
+ start_id = subject.send(:random_start_id)
+ expect(start_id).to be_between(Namespace.first.id, Namespace.last.id).inclusive
+ end
+ end
+ end
+
+ describe '#execute' do
+ let(:empty_results) do
+ { batches: 0, matches: 0, mismatches: 0, mismatches_details: [] }
+ end
+
+ context 'when empty tables' do
+ it 'returns results with zero counters' do
+ result = consistency_check_service.execute
+
+ expect(result).to eq(empty_results)
+ end
+
+ it 'does not call the ConsistencyCheckService' do
+ expect(Gitlab::Database::ConsistencyChecker).not_to receive(:new)
+ consistency_check_service.execute
+ end
+ end
+
+ context 'no cursor has been saved before' do
+ let(:selected_start_id) { Namespace.order(:id).limit(5).pluck(:id).last }
+ let(:expected_next_start_id) { selected_start_id + batch_size * max_batches }
+
+ before do
+ create_list(:namespace, 50) # This will also create Ci::NameSpaceMirror objects
+ expect(consistency_check_service).to receive(:random_start_id).and_return(selected_start_id)
+ end
+
+ it 'picks a random start_id' do
+ expected_result = {
+ batches: 2,
+ matches: 10,
+ mismatches: 0,
+ mismatches_details: [],
+ start_id: selected_start_id,
+ next_start_id: expected_next_start_id
+ }
+ expect(consistency_check_service.execute).to eq(expected_result)
+ end
+
+ it 'calls the ConsistencyCheckService with the expected parameters' do
+ allow_next_instance_of(Gitlab::Database::ConsistencyChecker) do |instance|
+ expect(instance).to receive(:execute).with(start_id: selected_start_id).and_return({
+ batches: 2,
+ next_start_id: expected_next_start_id,
+ matches: 10,
+ mismatches: 0,
+ mismatches_details: []
+ })
+ end
+
+ expect(Gitlab::Database::ConsistencyChecker).to receive(:new).with(
+ source_model: Namespace,
+ target_model: Ci::NamespaceMirror,
+ source_columns: %w[id traversal_ids],
+ target_columns: %w[namespace_id traversal_ids]
+ ).and_call_original
+
+ expected_result = {
+ batches: 2,
+ start_id: selected_start_id,
+ next_start_id: expected_next_start_id,
+ matches: 10,
+ mismatches: 0,
+ mismatches_details: []
+ }
+ expect(consistency_check_service.execute).to eq(expected_result)
+ end
+
+ it 'saves the next_start_id in Redis for he next iteration' do
+ expect(consistency_check_service).to receive(:save_next_start_id).with(expected_next_start_id).and_call_original
+ consistency_check_service.execute
+ end
+ end
+
+ context 'cursor saved in Redis and moving' do
+ let(:first_namespace_id) { Namespace.order(:id).first.id }
+ let(:second_namespace_id) { Namespace.order(:id).second.id }
+
+ before do
+ create_list(:namespace, 30) # This will also create Ci::NameSpaceMirror objects
+ end
+
+ it "keeps moving the cursor with each call to the service" do
+ expect(consistency_check_service).to receive(:random_start_id).at_most(:once).and_return(first_namespace_id)
+
+ allow_next_instance_of(Gitlab::Database::ConsistencyChecker) do |instance|
+ expect(instance).to receive(:execute).ordered.with(start_id: first_namespace_id).and_call_original
+ expect(instance).to receive(:execute).ordered.with(start_id: first_namespace_id + 10).and_call_original
+ expect(instance).to receive(:execute).ordered.with(start_id: first_namespace_id + 20).and_call_original
+ # Gets back to the start of the table
+ expect(instance).to receive(:execute).ordered.with(start_id: first_namespace_id).and_call_original
+ end
+
+ 4.times do
+ consistency_check_service.execute
+ end
+ end
+
+ it "keeps moving the cursor from any start point" do
+ expect(consistency_check_service).to receive(:random_start_id).at_most(:once).and_return(second_namespace_id)
+
+ allow_next_instance_of(Gitlab::Database::ConsistencyChecker) do |instance|
+ expect(instance).to receive(:execute).ordered.with(start_id: second_namespace_id).and_call_original
+ expect(instance).to receive(:execute).ordered.with(start_id: second_namespace_id + 10).and_call_original
+ end
+
+ 2.times do
+ consistency_check_service.execute
+ end
+ end
+ end
+ end
+end