Extract Geo::RepositoryVerificationPrimaryService

parent ef9c1792
module Geo
class RepositoryVerificationPrimaryService
include Gitlab::Geo::ProjectLogHelpers
def initialize(project)
@project = project
end
def execute
calculate_repository_checksum
calculate_wiki_checksum
end
private
attr_reader :project
def calculate_repository_checksum
calculate_checksum(:repository, project.repository)
end
def calculate_wiki_checksum
calculate_checksum(:wiki, project.wiki.repository)
end
def calculate_checksum(type, repository)
update_repository_state!(type, checksum: repository.checksum)
rescue Gitlab::Git::Repository::NoRepository, Gitlab::Git::Repository::InvalidRepository
update_repository_state!(type, checksum: Gitlab::Git::Repository::EMPTY_REPOSITORY_CHECKSUM)
rescue => e
log_error('Error calculating the repository checksum', e, type: type)
update_repository_state!(type, failure: e.message)
end
def update_repository_state!(type, checksum: nil, failure: nil)
repository_state.update!(
"#{type}_verification_checksum" => checksum,
"last_#{type}_verification_failure" => failure
)
end
def repository_state
@repository_state ||= project.repository_state || project.build_repository_state
end
end
end
......@@ -5,7 +5,6 @@ module Geo
include ApplicationWorker
include GeoQueue
include ExclusiveLeaseGuard
include Gitlab::Geo::ProjectLogHelpers
LEASE_TIMEOUT = 1.hour.to_i
......@@ -18,41 +17,12 @@ module Geo
return if project.nil? || project.pending_delete?
try_obtain_lease do
calculate_repository_checksum
calculate_wiki_checksum
Geo::RepositoryVerificationPrimaryService.new(project).execute
end
end
private
def calculate_repository_checksum
calculate_checksum(:repository, project.repository)
end
def calculate_wiki_checksum
calculate_checksum(:wiki, project.wiki.repository)
end
def calculate_checksum(type, repository)
update_repository_state!(type, checksum: repository.checksum)
rescue Gitlab::Git::Repository::NoRepository, Gitlab::Git::Repository::InvalidRepository
update_repository_state!(type, checksum: Gitlab::Git::Repository::EMPTY_REPOSITORY_CHECKSUM)
rescue => e
log_error('Error calculating the repository checksum', e, type: type)
update_repository_state!(type, failure: e.message)
end
def update_repository_state!(type, checksum: nil, failure: nil)
repository_state.update!(
"#{type}_verification_checksum" => checksum,
"last_#{type}_verification_failure" => failure
)
end
def repository_state
@repository_state ||= project.repository_state || project.build_repository_state
end
def lease_key
"geo:single_repository_verification_worker:#{project.id}"
end
......
require 'spec_helper'
describe Geo::RepositoryVerificationPrimaryService do
let(:project) { create(:project) }
let(:repository) { double(checksum: 'f123') }
let(:wiki) { double(checksum: 'e321') }
subject(:service) { described_class.new(project) }
describe '#perform' do
it 'calculates the checksum for unverified projects' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
subject.execute
expect(project.repository_state).to have_attributes(
repository_verification_checksum: 'f123',
last_repository_verification_failure: nil,
wiki_verification_checksum: 'e321',
last_wiki_verification_failure: nil
)
end
it 'calculates the checksum for outdated projects' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
repository_state =
create(:repository_state,
project: project,
repository_verification_checksum: nil,
wiki_verification_checksum: nil)
subject.execute
expect(repository_state.reload).to have_attributes(
repository_verification_checksum: 'f123',
last_repository_verification_failure: nil,
wiki_verification_checksum: 'e321',
last_wiki_verification_failure: nil
)
end
it 'calculates the checksum for outdated repositories/wikis' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
repository_state =
create(:repository_state,
project: project,
repository_verification_checksum: nil,
wiki_verification_checksum: nil)
subject.execute
expect(repository_state.reload).to have_attributes(
repository_verification_checksum: 'f123',
last_repository_verification_failure: nil,
wiki_verification_checksum: 'e321',
last_wiki_verification_failure: nil
)
end
it 'recalculates the checksum for projects up to date' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
create(:repository_state,
project: project,
repository_verification_checksum: 'f079a831cab27bcda7d81cd9b48296d0c3dd92ee',
wiki_verification_checksum: 'e079a831cab27bcda7d81cd9b48296d0c3dd92ef')
expect(repository).to receive(:checksum)
expect(wiki).to receive(:checksum)
subject.execute
end
it 'calculates the wiki checksum even when wiki is not enabled for project' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
project.update!(wiki_enabled: false)
subject.execute
expect(project.repository_state).to have_attributes(
repository_verification_checksum: 'f123',
last_repository_verification_failure: nil,
wiki_verification_checksum: 'e321',
last_wiki_verification_failure: nil
)
end
it 'does not mark the calculating as failed when there is no repo' do
subject.execute
expect(project.repository_state).to have_attributes(
repository_verification_checksum: '0000000000000000000000000000000000000000',
last_repository_verification_failure: nil,
wiki_verification_checksum: '0000000000000000000000000000000000000000',
last_wiki_verification_failure: nil
)
end
it 'does not mark the calculating as failed for non-valid repo' do
project_broken_repo = create(:project, :broken_repo)
service = described_class.new(project_broken_repo)
service.execute
expect(project_broken_repo.repository_state).to have_attributes(
repository_verification_checksum: '0000000000000000000000000000000000000000',
last_repository_verification_failure: nil,
wiki_verification_checksum: '0000000000000000000000000000000000000000',
last_wiki_verification_failure: nil
)
end
it 'keeps track of failures when calculating the repository checksum' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
allow(repository).to receive(:checksum).and_raise('Something went wrong with repository')
allow(wiki).to receive(:checksum).twice.and_raise('Something went wrong with wiki')
subject.execute
expect(project.repository_state).to have_attributes(
repository_verification_checksum: nil,
last_repository_verification_failure: 'Something went wrong with repository',
wiki_verification_checksum: nil,
last_wiki_verification_failure: 'Something went wrong with wiki'
)
end
end
def stub_project_repository(project, repository)
allow(Repository).to receive(:new).with(
project.full_path,
project,
disk_path: project.disk_path
).and_return(repository)
end
def stub_wiki_repository(wiki, repository)
allow(Repository).to receive(:new).with(
project.wiki.full_path,
project,
disk_path: project.wiki.disk_path,
is_wiki: true
).and_return(repository)
end
end
......@@ -7,184 +7,45 @@ describe Geo::RepositoryVerification::Primary::SingleWorker, :postgresql, :clean
set(:project) { create(:project) }
let!(:primary) { create(:geo_node, :primary) }
let(:repository) { double(checksum: 'f123') }
let(:wiki) { double(checksum: 'e321') }
before do
stub_current_geo_node(primary)
stub_exclusive_lease
end
describe '#perform' do
it 'does not calculate the checksum when not running on a primary' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
allow(Gitlab::Geo).to receive(:primary?) { false }
expect(repository).not_to receive(:checksum)
expect(wiki).not_to receive(:checksum)
subject.perform(project.id)
expect(project.reload.repository_state).to be_nil
end
it 'does not calculate the checksum when project is pending deletion' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
project.update!(pending_delete: true)
expect(repository).not_to receive(:checksum)
expect(wiki).not_to receive(:checksum)
subject.perform(project.id)
expect(project.reload.repository_state).to be_nil
end
it 'does not raise an error when project could not be found' do
expect { subject.perform(-1) }.not_to raise_error
end
it 'calculates the checksum for unverified projects' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
subject.perform(project.id)
expect(project.repository_state).to have_attributes(
repository_verification_checksum: 'f123',
last_repository_verification_failure: nil,
wiki_verification_checksum: 'e321',
last_wiki_verification_failure: nil
)
end
it 'calculates the checksum for outdated projects' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
repository_state =
create(:repository_state,
project: project,
repository_verification_checksum: nil,
wiki_verification_checksum: nil)
subject.perform(project.id)
expect(repository_state.reload).to have_attributes(
repository_verification_checksum: 'f123',
last_repository_verification_failure: nil,
wiki_verification_checksum: 'e321',
last_wiki_verification_failure: nil
)
end
it 'calculates the checksum for outdated repositories/wikis' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
repository_state =
create(:repository_state,
project: project,
repository_verification_checksum: nil,
wiki_verification_checksum: nil)
subject.perform(project.id)
expect(repository_state.reload).to have_attributes(
repository_verification_checksum: 'f123',
last_repository_verification_failure: nil,
wiki_verification_checksum: 'e321',
last_wiki_verification_failure: nil
)
end
it 'recalculates the checksum for projects up to date' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
it 'delegates the checksum calculation to Geo::RepositoryVerificationPrimaryService' do
stub_exclusive_lease
create(:repository_state,
project: project,
repository_verification_checksum: 'f079a831cab27bcda7d81cd9b48296d0c3dd92ee',
wiki_verification_checksum: 'e079a831cab27bcda7d81cd9b48296d0c3dd92ef')
service = instance_double(Geo::RepositoryVerificationPrimaryService, execute: true)
expect(repository).to receive(:checksum)
expect(wiki).to receive(:checksum)
allow(Geo::RepositoryVerificationPrimaryService)
.to receive(:new)
.with(project)
.and_return(service)
subject.perform(project.id)
end
it 'calculates the wiki checksum even when wiki is not enabled for project' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
project.update!(wiki_enabled: false)
subject.perform(project.id)
expect(project.repository_state).to have_attributes(
repository_verification_checksum: 'f123',
last_repository_verification_failure: nil,
wiki_verification_checksum: 'e321',
last_wiki_verification_failure: nil
)
end
it 'does not mark the calculating as failed when there is no repo' do
subject.perform(project.id)
expect(project.repository_state).to have_attributes(
repository_verification_checksum: '0000000000000000000000000000000000000000',
last_repository_verification_failure: nil,
wiki_verification_checksum: '0000000000000000000000000000000000000000',
last_wiki_verification_failure: nil
)
expect(service).to have_received(:execute)
end
it 'does not mark the calculating as failed for non-valid repo' do
project_broken_repo = create(:project, :broken_repo)
subject.perform(project_broken_repo.id)
expect(project_broken_repo.repository_state).to have_attributes(
repository_verification_checksum: '0000000000000000000000000000000000000000',
last_repository_verification_failure: nil,
wiki_verification_checksum: '0000000000000000000000000000000000000000',
last_wiki_verification_failure: nil
)
end
it 'keeps track of failures when calculating the repository checksum' do
stub_project_repository(project, repository)
stub_wiki_repository(project.wiki, wiki)
allow(repository).to receive(:checksum).and_raise('Something went wrong with repository')
allow(wiki).to receive(:checksum).twice.and_raise('Something went wrong with wiki')
subject.perform(project.id)
expect(project.repository_state).to have_attributes(
repository_verification_checksum: nil,
last_repository_verification_failure: 'Something went wrong with repository',
wiki_verification_checksum: nil,
last_wiki_verification_failure: 'Something went wrong with wiki'
)
end
end
def stub_project_repository(project, repository)
allow(Repository).to receive(:new).with(
project.full_path,
project,
disk_path: project.disk_path
).and_return(repository)
end
def stub_wiki_repository(wiki, repository)
allow(Repository).to receive(:new).with(
project.wiki.full_path,
project,
disk_path: project.wiki.disk_path,
is_wiki: true
).and_return(repository)
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