Commit 4f6824c9 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch 'mk/verification-refactors' into 'master'

Geo: Verification-related refactors

See merge request gitlab-org/gitlab!47361
parents ba4c33fb ad17544e
...@@ -65,9 +65,5 @@ module Geo ...@@ -65,9 +65,5 @@ module Geo
def deleted_params def deleted_params
{ model_record_id: model_record.id, blob_path: blob_path } { model_record_id: model_record.id, blob_path: blob_path }
end end
def schedule_checksum_calculation
Geo::VerificationWorker.perform_async(replicable_name, model_record.id)
end
end end
end end
...@@ -25,10 +25,6 @@ module Geo ...@@ -25,10 +25,6 @@ module Geo
Feature.enabled?(:geo_framework_verification) Feature.enabled?(:geo_framework_verification)
end end
def checksummed
model.available_replicables.checksummed
end
def checksummed_count def checksummed_count
# When verification is disabled, this returns nil. # When verification is disabled, this returns nil.
# Bonus: This causes the progress bar to be hidden. # Bonus: This causes the progress bar to be hidden.
...@@ -47,11 +43,15 @@ module Geo ...@@ -47,11 +43,15 @@ module Geo
end end
def after_verifiable_update def after_verifiable_update
schedule_checksum_calculation if needs_checksum? verify_async if needs_checksum?
end
def verify_async
Geo::VerificationWorker.perform_async(replicable_name, model_record.id)
end end
def calculate_checksum! def verify
checksum = model_record.calculate_checksum! checksum = model_record.calculate_checksum
update_verification_state!(checksum: checksum) update_verification_state!(checksum: checksum)
rescue => e rescue => e
log_error('Error calculating the checksum', e) log_error('Error calculating the checksum', e)
...@@ -106,9 +106,5 @@ module Geo ...@@ -106,9 +106,5 @@ module Geo
retry_count = model_record.verification_retry_count.to_i + 1 retry_count = model_record.verification_retry_count.to_i + 1
[next_retry_time(retry_count), retry_count] [next_retry_time(retry_count), retry_count]
end end
def schedule_checksum_calculation
raise NotImplementedError
end
end end
end end
...@@ -36,7 +36,7 @@ module Geo ...@@ -36,7 +36,7 @@ module Geo
end end
def verify_checksum def verify_checksum
checksum = model_record.calculate_checksum! checksum = model_record.calculate_checksum
if mismatch?(checksum) if mismatch?(checksum)
update_registry!(mismatch: checksum, failure: 'checksum mismatch') update_registry!(mismatch: checksum, failure: 'checksum mismatch')
......
...@@ -14,7 +14,7 @@ module Geo ...@@ -14,7 +14,7 @@ module Geo
def perform(replicable_name, replicable_id) def perform(replicable_name, replicable_id)
replicator = ::Gitlab::Geo::Replicator.for_replicable_params(replicable_name: replicable_name, replicable_id: replicable_id) replicator = ::Gitlab::Geo::Replicator.for_replicable_params(replicable_name: replicable_name, replicable_id: replicable_id)
replicator.calculate_checksum! replicator.verify
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
log_error("Couldn't find the record, skipping", replicable_name: replicable_name, replicable_id: replicable_id) log_error("Couldn't find the record, skipping", replicable_name: replicable_name, replicable_id: replicable_id)
end end
......
...@@ -46,13 +46,13 @@ module Gitlab ...@@ -46,13 +46,13 @@ module Gitlab
raise NotImplementedError, 'There is no Replicator defined for this model' raise NotImplementedError, 'There is no Replicator defined for this model'
end end
# Clear model verification checksum and force recalculation # Returns a checksum of the file (assumed to be a "blob" type)
def calculate_checksum! #
self.verification_checksum = nil # @return [String] SHA256 hash of the carrierwave file
def calculate_checksum
return unless needs_checksum? return unless checksummable?
self.verification_checksum = self.class.hexdigest(replicator.carrierwave_uploader.path) self.class.hexdigest(replicator.carrierwave_uploader.path)
end end
# Checks whether model needs checksum to be performed # Checks whether model needs checksum to be performed
......
...@@ -4,24 +4,19 @@ require 'spec_helper' ...@@ -4,24 +4,19 @@ require 'spec_helper'
RSpec.describe Packages::PackageFile, type: :model do RSpec.describe Packages::PackageFile, type: :model do
include ::EE::GeoHelpers include ::EE::GeoHelpers
describe '#calculate_checksum!' do describe '#calculate_checksum' do
let(:package_file) { create(:conan_package_file, :conan_recipe_file) } let(:package_file) { create(:conan_package_file, :conan_recipe_file) }
it 'sets `verification_checksum` to SHA256 sum of the file' do it 'returns SHA256 sum of the file' do
expected = Digest::SHA256.file(package_file.file.path).hexdigest expected = Digest::SHA256.file(package_file.file.path).hexdigest
expect { package_file.calculate_checksum! } expect(package_file.calculate_checksum).to eq(expected)
.to change { package_file.verification_checksum }.from(nil).to(expected)
end end
it 'sets `checksum` to nil for a non-existent file' do it 'returns nil for a non-existent file' do
checksum = Digest::SHA256.file(package_file.file.path).hexdigest
package_file.verification_checksum = checksum
allow(package_file).to receive(:file_exist?).and_return(false) allow(package_file).to receive(:file_exist?).and_return(false)
expect { package_file.calculate_checksum! } expect(package_file.calculate_checksum).to eq(nil)
.to change { package_file.verification_checksum }.from(checksum).to(nil)
end end
end end
......
...@@ -6,4 +6,8 @@ RSpec.describe Geo::PackageFileReplicator do ...@@ -6,4 +6,8 @@ RSpec.describe Geo::PackageFileReplicator do
let(:model_record) { build(:package_file, :npm) } let(:model_record) { build(:package_file, :npm) }
include_examples 'a blob replicator' include_examples 'a blob replicator'
# TODO: Move these examples to the blob and repo strategy shared examples so
# these get run for all Replicators.
# https://gitlab.com/gitlab-org/gitlab/-/issues/280768
it_behaves_like 'a verifiable replicator'
end end
...@@ -21,7 +21,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do ...@@ -21,7 +21,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do
it 'does not calculate the checksum when not running on a secondary' do it 'does not calculate the checksum when not running on a secondary' do
stub_primary_node stub_primary_node
expect(package_file).not_to receive(:calculate_checksum!) expect(package_file).not_to receive(:calculate_checksum)
service.execute service.execute
end end
...@@ -29,7 +29,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do ...@@ -29,7 +29,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do
it 'does not verify the checksum if resync is needed' do it 'does not verify the checksum if resync is needed' do
registry.resync registry.resync
expect(package_file).not_to receive(:calculate_checksum!) expect(package_file).not_to receive(:calculate_checksum)
service.execute service.execute
end end
...@@ -37,7 +37,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do ...@@ -37,7 +37,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do
it 'does not verify the checksum if sync is started' do it 'does not verify the checksum if sync is started' do
registry.start! registry.start!
expect(package_file).not_to receive(:calculate_checksum!) expect(package_file).not_to receive(:calculate_checksum)
service.execute service.execute
end end
...@@ -45,7 +45,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do ...@@ -45,7 +45,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do
it 'does not verify the checksum if primary was never verified' do it 'does not verify the checksum if primary was never verified' do
package_file.assign_attributes(verification_checksum: nil) package_file.assign_attributes(verification_checksum: nil)
expect(package_file).not_to receive(:calculate_checksum!) expect(package_file).not_to receive(:calculate_checksum)
service.execute service.execute
end end
...@@ -54,13 +54,13 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do ...@@ -54,13 +54,13 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do
package_file.assign_attributes(verification_checksum: '62fc1ec4ce60') package_file.assign_attributes(verification_checksum: '62fc1ec4ce60')
registry.update(verification_checksum: '62fc1ec4ce60') registry.update(verification_checksum: '62fc1ec4ce60')
expect(package_file).not_to receive(:calculate_checksum!) expect(package_file).not_to receive(:calculate_checksum)
service.execute service.execute
end end
it 'sets checksum when the checksum matches' do it 'sets checksum when the checksum matches' do
allow(package_file).to receive(:calculate_checksum!).and_return('62fc1ec4ce60') allow(package_file).to receive(:calculate_checksum).and_return('62fc1ec4ce60')
service.execute service.execute
...@@ -77,7 +77,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do ...@@ -77,7 +77,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do
context 'when the checksum mismatch' do context 'when the checksum mismatch' do
before do before do
allow(package_file).to receive(:calculate_checksum!).and_return('99fc1ec4ce60') allow(package_file).to receive(:calculate_checksum).and_return('99fc1ec4ce60')
end end
it 'keeps track of failures' do it 'keeps track of failures' do
...@@ -109,7 +109,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do ...@@ -109,7 +109,7 @@ RSpec.describe Geo::BlobVerificationSecondaryService, :geo do
context 'when checksum calculation fails' do context 'when checksum calculation fails' do
before do before do
allow(package_file).to receive(:calculate_checksum!).and_raise('Error calculating checksum') allow(package_file).to receive(:calculate_checksum).and_raise('Error calculating checksum')
end end
it 'keeps track of failures' do it 'keeps track of failures' do
......
...@@ -19,7 +19,6 @@ RSpec.shared_examples 'a blob replicator' do ...@@ -19,7 +19,6 @@ 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'
......
...@@ -19,7 +19,6 @@ RSpec.shared_examples 'a repository replicator' do ...@@ -19,7 +19,6 @@ RSpec.shared_examples 'a repository 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'
......
# frozen_string_literal: true # frozen_string_literal: true
# This is included by BlobReplicatorStrategy and RepositoryReplicatorStrategy. # This should be included on any Replicator which implements verification.
# #
RSpec.shared_examples 'a verifiable replicator' do RSpec.shared_examples 'a verifiable replicator' do
include EE::GeoHelpers include EE::GeoHelpers
...@@ -40,34 +40,34 @@ RSpec.shared_examples 'a verifiable replicator' do ...@@ -40,34 +40,34 @@ RSpec.shared_examples 'a verifiable replicator' do
end end
describe '#after_verifiable_update' do describe '#after_verifiable_update' do
it 'schedules the checksum calculation if needed' do it 'calls verify_async if needed' do
expect(replicator).to receive(:schedule_checksum_calculation) expect(replicator).to receive(:verify_async)
expect(replicator).to receive(:needs_checksum?).and_return(true) expect(replicator).to receive(:needs_checksum?).and_return(true)
replicator.after_verifiable_update replicator.after_verifiable_update
end end
end end
describe '#calculate_checksum!' do describe '#verify' do
before do before do
model_record.save! model_record.save!
end end
it 'calculates the checksum' do it 'calculates the checksum' do
expect(model_record).to receive(:calculate_checksum!).and_return('abc123') expect(model_record).to receive(:calculate_checksum).and_return('abc123')
replicator.calculate_checksum! replicator.verify
expect(model_record.reload.verification_checksum).to eq('abc123') expect(model_record.reload.verification_checksum).to eq('abc123')
expect(model_record.verified_at).not_to be_nil expect(model_record.verified_at).not_to be_nil
end end
it 'saves the error message and increments retry counter' do it 'saves the error message and increments retry counter' do
allow(model_record).to receive(:calculate_checksum!) do allow(model_record).to receive(:calculate_checksum) do
raise StandardError.new('Failure to calculate checksum') raise StandardError.new('Failure to calculate checksum')
end end
replicator.calculate_checksum! replicator.verify
expect(model_record.reload.verification_failure).to eq 'Failure to calculate checksum' expect(model_record.reload.verification_failure).to eq 'Failure to calculate checksum'
expect(model_record.verification_retry_count).to be 1 expect(model_record.verification_retry_count).to be 1
......
...@@ -9,11 +9,11 @@ RSpec.describe Geo::VerificationWorker, :geo do ...@@ -9,11 +9,11 @@ RSpec.describe Geo::VerificationWorker, :geo do
let(:job_args) { ['package_file', package_file.id] } let(:job_args) { ['package_file', package_file.id] }
describe '#perform' do describe '#perform' do
it 'calls calculate_checksum!' do it 'calls verify' do
replicator = double(:replicator) replicator = double(:replicator)
allow(::Gitlab::Geo::Replicator).to receive(:for_replicable_params).with(replicable_name: 'package_file', replicable_id: package_file.id).and_return(replicator) allow(::Gitlab::Geo::Replicator).to receive(:for_replicable_params).with(replicable_name: 'package_file', replicable_id: package_file.id).and_return(replicator)
expect(replicator).to receive(:calculate_checksum!) expect(replicator).to receive(:verify)
described_class.new.perform(*job_args) described_class.new.perform(*job_args)
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