Commit d166eecc authored by Mike Kozono's avatar Mike Kozono

Refactor: Extract VerifiableReplicator concern

from BlobReplicatorStrategy
parent 33a3220f
......@@ -4,7 +4,7 @@ module Geo
module BlobReplicatorStrategy
extend ActiveSupport::Concern
include Delay
include ::Geo::VerifiableReplicator
include Gitlab::Geo::LogHelpers
included do
......@@ -17,7 +17,8 @@ module Geo
return unless self.class.enabled?
publish(:created, **created_params)
schedule_checksum_calculation if needs_checksum?
after_verifiable_update
end
# Called by Gitlab::Geo::Replicator#consume
......@@ -47,45 +48,8 @@ module Geo
carrierwave_uploader.path
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
# 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
::Geo::BlobDownloadService.new(replicator: self).execute
end
......
# frozen_string_literal: true
module Geo
module VerifiableReplicator
extend ActiveSupport::Concern
include Delay
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
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
end
end
......@@ -19,6 +19,7 @@ RSpec.shared_examples 'a blob replicator' do
end
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.
include_examples 'a replicable model'
......@@ -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 })
end
it 'schedules the checksum calculation if needed' do
expect(Geo::BlobVerificationPrimaryWorker).to receive(:perform_async)
expect(replicator).to receive(:needs_checksum?).and_return(true)
it 'calls #after_verifiable_update' do
expect(replicator).to receive(:after_verifiable_update)
replicator.handle_after_create_commit
end
......@@ -45,8 +45,8 @@ RSpec.shared_examples 'a blob replicator' do
stub_feature_flags(replicator.replication_enabled_feature_key => false)
end
it 'does not schedule the checksum calculation' do
expect(Geo::BlobVerificationPrimaryWorker).not_to receive(:perform_async)
it 'does not call #after_verifiable_update' do
expect(replicator).not_to receive(:after_verifiable_update)
replicator.handle_after_create_commit
end
......@@ -82,30 +82,6 @@ RSpec.shared_examples 'a blob replicator' do
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
context "when the blob's project is in replicables for this geo node" 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