gitlab-org--gitlab-foss/spec/services/database/consistency_check_service_s...

155 lines
5.3 KiB
Ruby

# 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