Commit bef48d8a authored by Alishan Ladhani's avatar Alishan Ladhani

Refactor to haves stateful observers per migration

To improve ergonomics
parent f55df3d8
...@@ -9,8 +9,8 @@ module Gitlab ...@@ -9,8 +9,8 @@ module Gitlab
attr_reader :observations attr_reader :observations
def initialize(observers = ::Gitlab::Database::Migrations::Observers.all_observers) def initialize(observer_classes = ::Gitlab::Database::Migrations::Observers.all_observers)
@observers = observers @observer_classes = observer_classes
@observations = [] @observations = []
end end
...@@ -18,9 +18,11 @@ module Gitlab ...@@ -18,9 +18,11 @@ module Gitlab
observation = Observation.new(version, name) observation = Observation.new(version, name)
observation.success = true observation.success = true
observers = observer_classes.map { |c| c.new(observation) }
exception = nil exception = nil
on_each_observer { |observer| observer.before } on_each_observer(observers) { |observer| observer.before }
observation.walltime = Benchmark.realtime do observation.walltime = Benchmark.realtime do
yield yield
...@@ -29,8 +31,8 @@ module Gitlab ...@@ -29,8 +31,8 @@ module Gitlab
observation.success = false observation.success = false
end end
on_each_observer { |observer| observer.after } on_each_observer(observers) { |observer| observer.after }
on_each_observer { |observer| observer.record(observation) } on_each_observer(observers) { |observer| observer.record }
record_observation(observation) record_observation(observation)
...@@ -41,13 +43,13 @@ module Gitlab ...@@ -41,13 +43,13 @@ module Gitlab
private private
attr_reader :observers attr_reader :observer_classes
def record_observation(observation) def record_observation(observation)
@observations << observation @observations << observation
end end
def on_each_observer(&block) def on_each_observer(observers, &block)
observers.each do |observer| observers.each do |observer|
yield observer yield observer
rescue StandardError => e rescue StandardError => e
......
...@@ -6,10 +6,10 @@ module Gitlab ...@@ -6,10 +6,10 @@ module Gitlab
module Observers module Observers
def self.all_observers def self.all_observers
[ [
TotalDatabaseSizeChange.new, TotalDatabaseSizeChange,
QueryStatistics.new, QueryStatistics,
QueryLog.new, QueryLog,
QueryDetails.new QueryDetails
] ]
end end
end end
......
...@@ -5,10 +5,11 @@ module Gitlab ...@@ -5,10 +5,11 @@ module Gitlab
module Migrations module Migrations
module Observers module Observers
class MigrationObserver class MigrationObserver
attr_reader :connection attr_reader :connection, :observation
def initialize def initialize(observation)
@connection = ActiveRecord::Base.connection @connection = ActiveRecord::Base.connection
@observation = observation
end end
def before def before
...@@ -19,7 +20,7 @@ module Gitlab ...@@ -19,7 +20,7 @@ module Gitlab
# implement in subclass # implement in subclass
end end
def record(observation) def record
raise NotImplementedError, 'implement in subclass' raise NotImplementedError, 'implement in subclass'
end end
end end
......
...@@ -22,7 +22,7 @@ module Gitlab ...@@ -22,7 +22,7 @@ module Gitlab
@file.close @file.close
end end
def record(observation) def record
File.rename(@file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}-query-details.json")) File.rename(@file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}-query-details.json"))
end end
......
...@@ -17,7 +17,7 @@ module Gitlab ...@@ -17,7 +17,7 @@ module Gitlab
@logger.close @logger.close
end end
def record(observation) def record
File.rename(@log_file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}.log")) File.rename(@log_file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}.log"))
end end
end end
......
...@@ -16,7 +16,7 @@ module Gitlab ...@@ -16,7 +16,7 @@ module Gitlab
connection.execute('select pg_stat_statements_reset()') connection.execute('select pg_stat_statements_reset()')
end end
def record(observation) def record
return unless enabled? return unless enabled?
observation.query_statistics = connection.execute(<<~SQL) observation.query_statistics = connection.execute(<<~SQL)
......
...@@ -13,7 +13,7 @@ module Gitlab ...@@ -13,7 +13,7 @@ module Gitlab
@size_after = get_total_database_size @size_after = get_total_database_size
end end
def record(observation) def record
return unless @size_after && @size_before return unless @size_after && @size_before
observation.total_database_size_change = @size_after - @size_before observation.total_database_size_change = @size_after - @size_before
......
...@@ -13,17 +13,27 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do ...@@ -13,17 +13,27 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
end end
context 'behavior with observers' do context 'behavior with observers' do
subject { described_class.new(observers).observe(version: migration_version, name: migration_name) {} } subject { described_class.new([Gitlab::Database::Migrations::Observers::MigrationObserver]).observe(version: migration_version, name: migration_name) {} }
let(:observers) { [observer] }
let(:observer) { instance_double('Gitlab::Database::Migrations::Observers::MigrationObserver', before: nil, after: nil, record: nil) } let(:observer) { instance_double('Gitlab::Database::Migrations::Observers::MigrationObserver', before: nil, after: nil, record: nil) }
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)
.with(instance_of(Gitlab::Database::Migrations::Observation)) { |observation| expect(observation.version).to eq(migration_version) }
.and_return(observer)
subject
end
it 'calls #before, #after, #record on given observers' do it 'calls #before, #after, #record on given observers' do
expect(observer).to receive(:before).ordered expect(observer).to receive(:before).ordered
expect(observer).to receive(:after).ordered expect(observer).to receive(:after).ordered
expect(observer).to receive(:record).ordered do |observation| expect(observer).to receive(:record).ordered
expect(observation.version).to eq(migration_version)
end
subject subject
end end
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do
subject { described_class.new } subject { described_class.new(observation) }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) } let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
let(:connection) { ActiveRecord::Base.connection } let(:connection) { ActiveRecord::Base.connection }
...@@ -50,7 +50,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do ...@@ -50,7 +50,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do
subject.before subject.before
run_query run_query
subject.after subject.after
subject.record(observation) subject.record
end end
def run_query def run_query
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do
subject { described_class.new } subject { described_class.new(observation) }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) } let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
let(:connection) { ActiveRecord::Base.connection } let(:connection) { ActiveRecord::Base.connection }
...@@ -34,6 +34,6 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do ...@@ -34,6 +34,6 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do
subject.before subject.before
connection.execute(query) connection.execute(query)
subject.after subject.after
subject.record(observation) subject.record
end end
end end
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do
subject { described_class.new } subject { described_class.new(observation) }
let(:observation) { Gitlab::Database::Migrations::Observation.new }
let(:connection) { ActiveRecord::Base.connection } let(:connection) { ActiveRecord::Base.connection }
def mock_pgss(enabled: true) def mock_pgss(enabled: true)
...@@ -37,7 +38,6 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do ...@@ -37,7 +38,6 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do
end end
describe '#record' do describe '#record' do
let(:observation) { Gitlab::Database::Migrations::Observation.new }
let(:result) { double } let(:result) { double }
let(:pgss_query) do let(:pgss_query) do
<<~SQL <<~SQL
...@@ -52,7 +52,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do ...@@ -52,7 +52,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do
mock_pgss(enabled: true) mock_pgss(enabled: true)
expect(connection).to receive(:execute).with(pgss_query).once.and_return(result) expect(connection).to receive(:execute).with(pgss_query).once.and_return(result)
expect { subject.record(observation) }.to change { observation.query_statistics }.from(nil).to(result) expect { subject.record }.to change { observation.query_statistics }.from(nil).to(result)
end end
end end
...@@ -61,7 +61,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do ...@@ -61,7 +61,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do
mock_pgss(enabled: false) mock_pgss(enabled: false)
expect(connection).not_to receive(:execute) expect(connection).not_to receive(:execute)
expect { subject.record(observation) }.not_to change { observation.query_statistics } expect { subject.record }.not_to change { observation.query_statistics }
end end
end end
end end
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::TotalDatabaseSizeChange do RSpec.describe Gitlab::Database::Migrations::Observers::TotalDatabaseSizeChange do
subject { described_class.new } subject { described_class.new(observation) }
let(:observation) { Gitlab::Database::Migrations::Observation.new } let(:observation) { Gitlab::Database::Migrations::Observation.new }
let(:connection) { ActiveRecord::Base.connection } let(:connection) { ActiveRecord::Base.connection }
...@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::TotalDatabaseSizeChange ...@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::TotalDatabaseSizeChange
subject.before subject.before
subject.after subject.after
subject.record(observation) subject.record
expect(observation.total_database_size_change).to eq(256 - 1024) expect(observation.total_database_size_change).to eq(256 - 1024)
end end
...@@ -27,13 +27,13 @@ RSpec.describe Gitlab::Database::Migrations::Observers::TotalDatabaseSizeChange ...@@ -27,13 +27,13 @@ RSpec.describe Gitlab::Database::Migrations::Observers::TotalDatabaseSizeChange
it 'does not record anything if before size is unknown' do it 'does not record anything if before size is unknown' do
subject.after subject.after
expect { subject.record(observation) }.not_to change { observation.total_database_size_change } expect { subject.record }.not_to change { observation.total_database_size_change }
end end
it 'does not record anything if after size is unknown' do it 'does not record anything if after size is unknown' do
subject.before subject.before
expect { subject.record(observation) }.not_to change { observation.total_database_size_change } expect { subject.record }.not_to change { observation.total_database_size_change }
end end
end end
end end
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