Commit 451fbf0c authored by Mark Chao's avatar Mark Chao

Merge branch 'mk/refactor-extract-verification' into 'master'

Geo: Refactor: Extract verification concern

See merge request gitlab-org/gitlab!45695
parents 3285fc6f 29bc64b4
...@@ -4,7 +4,7 @@ module Geo ...@@ -4,7 +4,7 @@ module Geo
module BlobReplicatorStrategy module BlobReplicatorStrategy
extend ActiveSupport::Concern extend ActiveSupport::Concern
include Delay include ::Geo::VerifiableReplicator
include Gitlab::Geo::LogHelpers include Gitlab::Geo::LogHelpers
included do included do
...@@ -17,7 +17,8 @@ module Geo ...@@ -17,7 +17,8 @@ module Geo
return unless self.class.enabled? return unless self.class.enabled?
publish(:created, **created_params) publish(:created, **created_params)
schedule_checksum_calculation if needs_checksum?
after_verifiable_update
end end
# Called by Gitlab::Geo::Replicator#consume # Called by Gitlab::Geo::Replicator#consume
...@@ -47,45 +48,8 @@ module Geo ...@@ -47,45 +48,8 @@ module Geo
carrierwave_uploader.path carrierwave_uploader.path
end end
def calculate_checksum!
checksum = model_record.calculate_checksum!
update_verification_state!(checksum: checksum)
rescue => e
log_error('Error calculating the checksum', e)
update_verification_state!(failure: e.message)
end
# Check if given checksum matches known one
#
# @param [String] checksum
# @return [Boolean] whether checksum matches
def matches_checksum?(checksum)
model_record.verification_checksum == checksum
end
private private
# Update checksum on Geo primary database
#
# @param [String] checksum value generated by the checksum routine
# @param [String] failure (optional) stacktrace from failed execution
def update_verification_state!(checksum: nil, failure: nil)
retry_at, retry_count = calculate_next_retry_attempt if failure.present?
model_record.update!(
verification_checksum: checksum,
verified_at: Time.current,
verification_failure: failure,
verification_retry_at: retry_at,
verification_retry_count: retry_count
)
end
def calculate_next_retry_attempt
retry_count = model_record.verification_retry_count.to_i + 1
[next_retry_time(retry_count), retry_count]
end
def download def download
::Geo::BlobDownloadService.new(replicator: self).execute ::Geo::BlobDownloadService.new(replicator: self).execute
end end
......
...@@ -4,7 +4,7 @@ module Geo ...@@ -4,7 +4,7 @@ module Geo
module RepositoryReplicatorStrategy module RepositoryReplicatorStrategy
extend ActiveSupport::Concern extend ActiveSupport::Concern
include Delay include ::Geo::VerifiableReplicator
include Gitlab::Geo::LogHelpers include Gitlab::Geo::LogHelpers
included do included do
......
# frozen_string_literal: true
module Geo
module VerifiableReplicator
extend ActiveSupport::Concern
include Delay
class_methods do
def checksummed
model.available_replicables.checksummed
end
def checksummed_count
model.available_replicables.checksummed.count
end
def checksum_failed_count
model.available_replicables.checksum_failed.count
end
end
def after_verifiable_update
schedule_checksum_calculation if needs_checksum?
end
def calculate_checksum!
checksum = model_record.calculate_checksum!
update_verification_state!(checksum: checksum)
rescue => e
log_error('Error calculating the checksum', e)
update_verification_state!(failure: e.message)
end
# Check if given checksum matches known one
#
# @param [String] checksum
# @return [Boolean] whether checksum matches
def matches_checksum?(checksum)
model_record.verification_checksum == checksum
end
def needs_checksum?
return true unless model_record.respond_to?(:needs_checksum?)
model_record.needs_checksum?
end
# Checksum value from the main database
#
# @abstract
def primary_checksum
model_record.verification_checksum
end
def secondary_checksum
registry.verification_checksum
end
private
# Update checksum on Geo primary database
#
# @param [String] checksum value generated by the checksum routine
# @param [String] failure (optional) stacktrace from failed execution
def update_verification_state!(checksum: nil, failure: nil)
retry_at, retry_count = calculate_next_retry_attempt if failure.present?
model_record.update!(
verification_checksum: checksum,
verified_at: Time.current,
verification_failure: failure,
verification_retry_at: retry_at,
verification_retry_count: retry_count
)
end
def calculate_next_retry_attempt
retry_count = model_record.verification_retry_count.to_i + 1
[next_retry_time(retry_count), retry_count]
end
def schedule_checksum_calculation
raise NotImplementedError
end
end
end
...@@ -134,18 +134,6 @@ module Gitlab ...@@ -134,18 +134,6 @@ module Gitlab
replicator_class.new(model_record_id: replicable_id) replicator_class.new(model_record_id: replicable_id)
end end
def self.checksummed
model.available_replicables.checksummed
end
def self.checksummed_count
model.available_replicables.checksummed.count
end
def self.checksum_failed_count
model.available_replicables.checksum_failed.count
end
def self.primary_total_count def self.primary_total_count
model.available_replicables.count model.available_replicables.count
end end
...@@ -265,17 +253,6 @@ module Gitlab ...@@ -265,17 +253,6 @@ module Gitlab
registry_class.for_model_record_id(model_record_id) registry_class.for_model_record_id(model_record_id)
end end
# Checksum value from the main database
#
# @abstract
def primary_checksum
model_record.verification_checksum
end
def secondary_checksum
registry.verification_checksum
end
# Return exactly the data needed by `for_replicable_params` to # Return exactly the data needed by `for_replicable_params` to
# reinstantiate this Replicator elsewhere. # reinstantiate this Replicator elsewhere.
# #
...@@ -298,10 +275,6 @@ module Gitlab ...@@ -298,10 +275,6 @@ module Gitlab
publish(:updated, **updated_params) publish(:updated, **updated_params)
end end
def schedule_checksum_calculation
raise NotImplementedError
end
def created_params def created_params
event_params event_params
end end
...@@ -318,12 +291,6 @@ module Gitlab ...@@ -318,12 +291,6 @@ module Gitlab
{ model_record_id: model_record.id } { model_record_id: model_record.id }
end end
def needs_checksum?
return true unless model_record.respond_to?(:needs_checksum?)
model_record.needs_checksum?
end
protected protected
# Store an event on the database # Store an event on the database
......
...@@ -19,6 +19,7 @@ RSpec.shared_examples 'a blob replicator' do ...@@ -19,6 +19,7 @@ RSpec.shared_examples 'a blob replicator' do
end end
it_behaves_like 'a replicator' it_behaves_like 'a replicator'
it_behaves_like 'a verifiable replicator'
# This could be included in each model's spec, but including it here is DRYer. # This could be included in each model's spec, but including it here is DRYer.
include_examples 'a replicable model' include_examples 'a replicable model'
...@@ -33,9 +34,8 @@ RSpec.shared_examples 'a blob replicator' do ...@@ -33,9 +34,8 @@ RSpec.shared_examples 'a blob replicator' do
"replicable_name" => replicator.replicable_name, "event_name" => "created", "payload" => { "model_record_id" => replicator.model_record.id }) "replicable_name" => replicator.replicable_name, "event_name" => "created", "payload" => { "model_record_id" => replicator.model_record.id })
end end
it 'schedules the checksum calculation if needed' do it 'calls #after_verifiable_update' do
expect(Geo::BlobVerificationPrimaryWorker).to receive(:perform_async) expect(replicator).to receive(:after_verifiable_update)
expect(replicator).to receive(:needs_checksum?).and_return(true)
replicator.handle_after_create_commit replicator.handle_after_create_commit
end end
...@@ -45,8 +45,8 @@ RSpec.shared_examples 'a blob replicator' do ...@@ -45,8 +45,8 @@ RSpec.shared_examples 'a blob replicator' do
stub_feature_flags(replicator.replication_enabled_feature_key => false) stub_feature_flags(replicator.replication_enabled_feature_key => false)
end end
it 'does not schedule the checksum calculation' do it 'does not call #after_verifiable_update' do
expect(Geo::BlobVerificationPrimaryWorker).not_to receive(:perform_async) expect(replicator).not_to receive(:after_verifiable_update)
replicator.handle_after_create_commit replicator.handle_after_create_commit
end end
...@@ -82,30 +82,6 @@ RSpec.shared_examples 'a blob replicator' do ...@@ -82,30 +82,6 @@ RSpec.shared_examples 'a blob replicator' do
end end
end end
describe '#calculate_checksum!' do
it 'calculates the checksum' do
model_record.save!
replicator.calculate_checksum!
expect(model_record.reload.verification_checksum).not_to be_nil
expect(model_record.reload.verified_at).not_to be_nil
end
it 'saves the error message and increments retry counter' do
model_record.save!
allow(model_record).to receive(:calculate_checksum!) do
raise StandardError.new('Failure to calculate checksum')
end
replicator.calculate_checksum!
expect(model_record.reload.verification_failure).to eq 'Failure to calculate checksum'
expect(model_record.verification_retry_count).to be 1
end
end
describe 'created event consumption' do describe 'created event consumption' do
context "when the blob's project is in replicables for this geo node" do context "when the blob's project is in replicables for this geo node" do
it 'invokes Geo::BlobDownloadService' do it 'invokes Geo::BlobDownloadService' do
......
# frozen_string_literal: true
# This is included by BlobReplicatorStrategy and RepositoryReplicatorStrategy.
#
RSpec.shared_examples 'a verifiable replicator' do
include EE::GeoHelpers
describe '#after_verifiable_update' do
it 'schedules the checksum calculation if needed' do
expect(replicator).to receive(:schedule_checksum_calculation)
expect(replicator).to receive(:needs_checksum?).and_return(true)
replicator.after_verifiable_update
end
end
describe '#calculate_checksum!' do
it 'calculates the checksum' do
model_record.save!
replicator.calculate_checksum!
expect(model_record.reload.verification_checksum).not_to be_nil
expect(model_record.reload.verified_at).not_to be_nil
end
it 'saves the error message and increments retry counter' do
model_record.save!
allow(model_record).to receive(:calculate_checksum!) do
raise StandardError.new('Failure to calculate checksum')
end
replicator.calculate_checksum!
expect(model_record.reload.verification_failure).to eq 'Failure to calculate checksum'
expect(model_record.verification_retry_count).to be 1
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