Commit cb5352fd authored by Jacob Vosmaer's avatar Jacob Vosmaer Committed by Douwe Maan

Make UpdateRepositoryStorageService idempotent

UpdateRepositoryStorageService moves a Git repository from its "old"
Gitaly shard to a "new" shard. This fixes a bug where if "old == new",
UpdateRepositoryStorageService would end up deleting your repository.
parent 7e217eb7
...@@ -4,11 +4,19 @@ module Projects ...@@ -4,11 +4,19 @@ module Projects
class UpdateRepositoryStorageService < BaseService class UpdateRepositoryStorageService < BaseService
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
RepositoryAlreadyMoved = Class.new(StandardError)
def initialize(project) def initialize(project)
@project = project @project = project
end end
def execute(new_repository_storage_key) def execute(new_repository_storage_key)
# Raising an exception is a little heavy handed but this behavior (doing
# nothing if the repo is already on the right storage) prevents data
# loss, so it is valuable for us to be able to observe it via the
# exception.
raise RepositoryAlreadyMoved if project.repository_storage == new_repository_storage_key
result = mirror_repository(new_repository_storage_key) result = mirror_repository(new_repository_storage_key)
if project.wiki.repository_exists? if project.wiki.repository_exists?
......
...@@ -7,5 +7,7 @@ class ProjectUpdateRepositoryStorageWorker ...@@ -7,5 +7,7 @@ class ProjectUpdateRepositoryStorageWorker
project = Project.find(project_id) project = Project.find(project_id)
::Projects::UpdateRepositoryStorageService.new(project).execute(new_repository_storage_key) ::Projects::UpdateRepositoryStorageService.new(project).execute(new_repository_storage_key)
rescue ::Projects::UpdateRepositoryStorageService::RepositoryAlreadyMoved
Rails.logger.info "#{self.class}: repository already moved: #{project}"
end end
end end
---
title: Make UpdateRepositoryStorageService idempotent
merge_request: 10457
author:
type: fixed
...@@ -32,6 +32,14 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -32,6 +32,14 @@ describe Projects::UpdateRepositoryStorageService do
end end
end end
context 'when the project is already on the target storage' do
it 'bails out and does nothing' do
expect do
subject.execute(project.repository_storage)
end.to raise_error(described_class::RepositoryAlreadyMoved)
end
end
context 'when the move fails' do context 'when the move fails' do
it 'unmarks the repository as read-only without updating the repository storage' do it 'unmarks the repository as read-only without updating the repository storage' do
expect_any_instance_of(Gitlab::Git::Repository).to receive(:fetch_repository_as_mirror) expect_any_instance_of(Gitlab::Git::Repository).to receive(:fetch_repository_as_mirror)
...@@ -90,6 +98,14 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -90,6 +98,14 @@ describe Projects::UpdateRepositoryStorageService do
end end
end end
context 'when the project is already on the target storage' do
it 'bails out and does nothing' do
expect do
subject.execute(project.repository_storage)
end.to raise_error(described_class::RepositoryAlreadyMoved)
end
end
context 'when the move of the wiki fails' do context 'when the move of the wiki fails' do
it 'unmarks the repository as read-only without updating the repository storage' do it 'unmarks the repository as read-only without updating the repository storage' do
expect(repository_double).to receive(:fetch_repository_as_mirror) expect(repository_double).to receive(:fetch_repository_as_mirror)
......
...@@ -12,5 +12,11 @@ describe ProjectUpdateRepositoryStorageWorker do ...@@ -12,5 +12,11 @@ describe ProjectUpdateRepositoryStorageWorker do
subject.perform(project.id, 'new_storage') subject.perform(project.id, 'new_storage')
end end
it 'catches and logs RepositoryAlreadyMoved' do
expect(Rails.logger).to receive(:info).with(/repository already moved/)
expect { subject.perform(project.id, project.repository_storage) }.not_to raise_error
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