Commit c8e6c91c authored by Tiago Botelho's avatar Tiago Botelho

Adds ExclusiveLeaseGuard to RepositoryRemoveRemoteWorker and restores...

Adds ExclusiveLeaseGuard to RepositoryRemoveRemoteWorker and restores RemoteMirror#refresh_remote to after_save callback
parent 08f402a0
class RepositoryRemoveRemoteWorker class RepositoryRemoveRemoteWorker
include ApplicationWorker include ApplicationWorker
include ExclusiveLeaseGuard
LEASE_TIMEOUT = 1.hour LEASE_TIMEOUT = 1.hour
def perform(project_id, remote_name) attr_reader :project, :remote_name
lease_uuid = try_obtain_lease(project_id)
return unless lease_uuid
project = Project.find(project_id) def perform(project_id, remote_name)
project.repository.remove_remote(remote_name) @remote_name = remote_name
@project = Project.find(project_id)
cancel_lease(project_id, lease_uuid) try_obtain_lease do
@project.repository.remove_remote(remote_name)
end end
private
def lease_key(project_id)
"remove_remote_#{project_id}"
end end
def try_obtain_lease(id) def lease_timeout
key = lease_key(id) LEASE_TIMEOUT
Gitlab::ExclusiveLease.new(key, timeout: LEASE_TIMEOUT).try_obtain
end end
def cancel_lease(id, uuid) def lease_key
key = lease_key(id) "remove_remote_#{project.id}_#{remote_name}"
Gitlab::ExclusiveLease.cancel(key, uuid)
end end
end end
...@@ -21,9 +21,10 @@ class RemoteMirror < ActiveRecord::Base ...@@ -21,9 +21,10 @@ class RemoteMirror < ActiveRecord::Base
validate :url_availability, if: -> (mirror) { mirror.url_changed? || mirror.enabled? } validate :url_availability, if: -> (mirror) { mirror.url_changed? || mirror.enabled? }
validates :url, addressable_url: true, if: :url_changed? validates :url, addressable_url: true, if: :url_changed?
before_save :refresh_remote, if: :mirror_url_changed? before_save :set_new_remote_name, if: :mirror_url_changed?
after_save :set_override_remote_mirror_available, unless: -> { Gitlab::CurrentSettings.current_application_settings.mirror_available } after_save :set_override_remote_mirror_available, unless: -> { Gitlab::CurrentSettings.current_application_settings.mirror_available }
after_save :refresh_remote, if: :mirror_url_changed?
after_update :reset_fields, if: :mirror_url_changed? after_update :reset_fields, if: :mirror_url_changed?
after_destroy :remove_remote after_destroy :remove_remote
...@@ -76,7 +77,7 @@ class RemoteMirror < ActiveRecord::Base ...@@ -76,7 +77,7 @@ class RemoteMirror < ActiveRecord::Base
return name if name return name if name
return unless id return unless id
"remote_mirror_#{id}" fallback_remote_name
end end
def update_failed? def update_failed?
...@@ -158,6 +159,10 @@ class RemoteMirror < ActiveRecord::Base ...@@ -158,6 +159,10 @@ class RemoteMirror < ActiveRecord::Base
@raw ||= Gitlab::Git::RemoteMirror.new(project.repository.raw, remote_name) @raw ||= Gitlab::Git::RemoteMirror.new(project.repository.raw, remote_name)
end end
def fallback_remote_name
"remote_mirror_#{id}"
end
def recently_scheduled? def recently_scheduled?
return false unless self.last_update_started_at return false unless self.last_update_started_at
...@@ -195,7 +200,7 @@ class RemoteMirror < ActiveRecord::Base ...@@ -195,7 +200,7 @@ class RemoteMirror < ActiveRecord::Base
project.update(remote_mirror_available_overridden: enabled) project.update(remote_mirror_available_overridden: enabled)
end end
def write_new_remote_name def set_new_remote_name
self.remote_name = "remote_mirror_#{SecureRandom.hex}" self.remote_name = "remote_mirror_#{SecureRandom.hex}"
end end
...@@ -204,12 +209,11 @@ class RemoteMirror < ActiveRecord::Base ...@@ -204,12 +209,11 @@ class RemoteMirror < ActiveRecord::Base
# Before adding a new remote we have to delete the data from # Before adding a new remote we have to delete the data from
# the previous remote name # the previous remote name
prev_remote_name = remote_name prev_remote_name = remote_name_was || fallback_remote_name
run_after_commit do run_after_commit do
project.repository.schedule_remove_remote(prev_remote_name) project.repository.schedule_remove_remote(prev_remote_name)
end end
write_new_remote_name
project.repository.add_remote(remote_name, url) project.repository.add_remote(remote_name, url)
end end
......
require 'rails_helper' require 'rails_helper'
describe RepositoryRemoveRemoteWorker do describe RepositoryRemoveRemoteWorker do
subject(:worker) { described_class.new }
describe '#perform' do describe '#perform' do
let(:remote_name) { 'joe'} let(:remote_name) { 'joe'}
let!(:project) { create(:project, :repository) } let!(:project) { create(:project, :repository) }
context 'when it does not get the lease' do context 'when it cannot obtain lease' do
it 'does not execute' do it 'logs error' do
allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain).and_return(false) allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain) { nil }
expect_any_instance_of(Repository).not_to receive(:remove_remote) expect_any_instance_of(Repository).not_to receive(:remove_remote)
expect(worker).to receive(:log_error).with('Cannot obtain an exclusive lease. There must be another instance already in execution.')
subject.perform(project.id, remote_name) worker.perform(project.id, remote_name)
end end
end end
...@@ -22,7 +25,7 @@ describe RepositoryRemoveRemoteWorker do ...@@ -22,7 +25,7 @@ describe RepositoryRemoveRemoteWorker do
context 'when project does not exist' do context 'when project does not exist' do
it 'returns nil' do it 'returns nil' do
expect { subject.perform(-1, 'remote_name') }.to raise_error(ActiveRecord::RecordNotFound) expect { worker.perform(-1, 'remote_name') }.to raise_error(ActiveRecord::RecordNotFound)
end end
end end
...@@ -34,7 +37,7 @@ describe RepositoryRemoveRemoteWorker do ...@@ -34,7 +37,7 @@ describe RepositoryRemoveRemoteWorker do
expect_any_instance_of(Repository).to receive(:remove_remote).with(remote_name).and_call_original expect_any_instance_of(Repository).to receive(:remove_remote).with(remote_name).and_call_original
subject.perform(project.id, remote_name) worker.perform(project.id, remote_name)
end 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