debian-mirror-gitlab/spec/lib/gitlab/database/migrations/instrumentation_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

151 lines
5.5 KiB
Ruby
Raw Normal View History

2021-03-11 19:13:27 +05:30
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Instrumentation do
2023-03-17 16:20:25 +05:30
subject(:instrumentation) { described_class.new(result_dir: result_dir) }
2021-11-18 22:05:49 +05:30
let(:result_dir) { Dir.mktmpdir }
2022-01-26 12:08:38 +05:30
let(:connection) { ActiveRecord::Migration.connection }
2021-11-18 22:05:49 +05:30
after do
FileUtils.rm_rf(result_dir)
end
2021-03-11 19:13:27 +05:30
describe '#observe' do
2022-06-21 17:19:12 +05:30
def load_observation(result_dir, migration_name)
Gitlab::Json.parse(File.read(File.join(result_dir, migration_name, described_class::STATS_FILENAME)))
end
2021-10-27 15:23:28 +05:30
let(:migration_name) { 'test' }
let(:migration_version) { '12345' }
2023-03-17 16:20:25 +05:30
let(:migration_meta) { { 'max_batch_size' => 1, 'total_tuple_count' => 10, 'interval' => 60 } }
2023-07-09 08:55:56 +05:30
let(:expected_json_keys) do
%w[version name walltime success total_database_size_change query_statistics error_message]
end
2021-03-11 19:13:27 +05:30
it 'executes the given block' do
2023-03-17 16:20:25 +05:30
expect do |b|
instrumentation.observe(version: migration_version, name: migration_name, connection: connection, meta: migration_meta, &b)
end.to yield_control
2021-03-11 19:13:27 +05:30
end
context 'behavior with observers' do
2022-01-26 12:08:38 +05:30
subject { described_class.new(observer_classes: [Gitlab::Database::Migrations::Observers::MigrationObserver], result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) {} }
2021-03-11 19:13:27 +05:30
let(:observer) { instance_double('Gitlab::Database::Migrations::Observers::MigrationObserver', before: nil, after: nil, record: nil) }
2021-10-27 15:23:28 +05:30
before do
allow(Gitlab::Database::Migrations::Observers::MigrationObserver).to receive(:new).and_return(observer)
end
it 'instantiates observer with observation' do
expect(Gitlab::Database::Migrations::Observers::MigrationObserver)
.to receive(:new)
2022-01-26 12:08:38 +05:30
.with(instance_of(Gitlab::Database::Migrations::Observation), anything, connection) { |observation| expect(observation.version).to eq(migration_version) }
2021-10-27 15:23:28 +05:30
.and_return(observer)
subject
end
2021-03-11 19:13:27 +05:30
it 'calls #before, #after, #record on given observers' do
expect(observer).to receive(:before).ordered
expect(observer).to receive(:after).ordered
2021-10-27 15:23:28 +05:30
expect(observer).to receive(:record).ordered
2021-03-11 19:13:27 +05:30
subject
end
it 'ignores errors coming from observers #before' do
expect(observer).to receive(:before).and_raise('some error')
subject
end
it 'ignores errors coming from observers #after' do
expect(observer).to receive(:after).and_raise('some error')
subject
end
it 'ignores errors coming from observers #record' do
expect(observer).to receive(:record).and_raise('some error')
subject
end
end
context 'on successful execution' do
2023-03-17 16:20:25 +05:30
subject do
instrumentation.observe(version: migration_version, name: migration_name,
connection: connection, meta: migration_meta) {}
end
2021-03-11 19:13:27 +05:30
2022-04-04 11:22:00 +05:30
it 'records a valid observation', :aggregate_failures do
2021-03-11 19:13:27 +05:30
expect(subject.walltime).not_to be_nil
expect(subject.success).to be_truthy
2021-10-27 15:23:28 +05:30
expect(subject.version).to eq(migration_version)
expect(subject.name).to eq(migration_name)
2023-04-23 21:23:45 +05:30
end
it 'transforms observation to expected json' do
expect(Gitlab::Json.parse(subject.to_json).keys).to contain_exactly(*expected_json_keys)
2021-03-11 19:13:27 +05:30
end
end
context 'upon failure' do
2023-07-09 08:55:56 +05:30
where(:exception, :error_message) do
[[StandardError, 'something went wrong'], [ActiveRecord::StatementTimeout, 'timeout']]
end
2021-03-11 19:13:27 +05:30
2022-04-04 11:22:00 +05:30
with_them do
2023-03-17 16:20:25 +05:30
subject(:observe) do
instrumentation.observe(version: migration_version, name: migration_name,
2023-07-09 08:55:56 +05:30
connection: connection, meta: migration_meta) { raise exception, error_message }
2021-10-27 15:23:28 +05:30
end
2022-04-04 11:22:00 +05:30
context 'retrieving observations' do
2022-06-21 17:19:12 +05:30
subject { load_observation(result_dir, migration_name) }
2022-04-04 11:22:00 +05:30
before do
observe
end
it 'records a valid observation', :aggregate_failures do
2022-06-21 17:19:12 +05:30
expect(subject['walltime']).not_to be_nil
expect(subject['success']).to be_falsey
expect(subject['version']).to eq(migration_version)
expect(subject['name']).to eq(migration_name)
2023-07-09 08:55:56 +05:30
expect(subject['error_message']).to eq(error_message)
2023-04-23 21:23:45 +05:30
end
it 'transforms observation to expected json' do
expect(Gitlab::Json.parse(subject.to_json).keys).to contain_exactly(*expected_json_keys)
2022-04-04 11:22:00 +05:30
end
2021-03-11 19:13:27 +05:30
end
end
end
context 'sequence of migrations with failures' do
let(:migration1) { double('migration1', call: nil) }
let(:migration2) { double('migration2', call: nil) }
2022-06-21 17:19:12 +05:30
let(:migration_name_2) { 'other_migration' }
let(:migration_version_2) { '98765' }
2021-03-11 19:13:27 +05:30
it 'records observations for all migrations' do
2023-03-17 16:20:25 +05:30
instrumentation.observe(version: migration_version, name: migration_name, connection: connection) {}
2022-08-27 11:52:29 +05:30
begin
2023-03-17 16:20:25 +05:30
instrumentation.observe(version: migration_version_2, name: migration_name_2, connection: connection) { raise 'something went wrong' }
2022-08-27 11:52:29 +05:30
rescue StandardError
nil
end
2022-06-21 17:19:12 +05:30
expect { load_observation(result_dir, migration_name) }.not_to raise_error
expect { load_observation(result_dir, migration_name_2) }.not_to raise_error
2021-03-11 19:13:27 +05:30
2022-06-21 17:19:12 +05:30
# Each observation is a subdirectory of the result_dir, so here we check that we didn't record an extra one
expect(Pathname(result_dir).children.map { |d| d.basename.to_s }).to contain_exactly(migration_name, migration_name_2)
2021-03-11 19:13:27 +05:30
end
end
end
end