Commit cbe2afc1 authored by Shinya Maeda's avatar Shinya Maeda

Clean up migrate! by splitting unsafe_migrate! and migrate!

parent 88984137
......@@ -201,43 +201,12 @@ module ObjectStorage
# new_store: Enum (Store::LOCAL, Store::REMOTE)
#
def migrate!(new_store)
return unless object_store != new_store
return unless file
uuid = Gitlab::ExclusiveLease.new(exclusive_lease_key, timeout: 1.hour.to_i).try_obtain
raise 'Already running' unless uuid
exclusive_lease_key = "object_storage_migrate:#{store_path}"
Gitlab::ExclusiveLease.new(exclusive_lease_key, timeout: 1.hour.to_i)
.try_obtain.tap do |uuid|
return unless uuid # rubocop:disable Lint/NonLocalExitFromIterator
begin
new_file = nil
file_to_delete = file
from_object_store = object_store
self.object_store = new_store # changes the storage and file
cache_stored_file! if file_storage?
with_callbacks(:migrate, file_to_delete) do
with_callbacks(:store, file_to_delete) do # for #store_versions!
new_file = storage.store!(file)
persist_object_store!
self.file = new_file
end
end
return file
rescue => e
# in case of failure delete new file
new_file.delete unless new_file.nil?
# revert back to the old file
self.object_store = from_object_store
self.file = file_to_delete
raise e
ensure
Gitlab::ExclusiveLease.cancel(exclusive_lease_key, uuid)
end
end
unsafe_migrate!(new_store)
ensure
Gitlab::ExclusiveLease.cancel(exclusive_lease_key, uuid)
end
def schedule_background_upload(*args)
......@@ -327,5 +296,43 @@ module ObjectStorage
raise UnknownStoreError
end
end
def exclusive_lease_key
"object_storage_migrate:#{model.class}:#{model.id}"
end
#
# Move the file to another store
#
# new_store: Enum (Store::LOCAL, Store::REMOTE)
#
def unsafe_migrate!(new_store)
return unless object_store != new_store
return unless file
new_file = nil
file_to_delete = file
from_object_store = object_store
self.object_store = new_store # changes the storage and file
cache_stored_file! if file_storage?
with_callbacks(:migrate, file_to_delete) do
with_callbacks(:store, file_to_delete) do # for #store_versions!
new_file = storage.store!(file)
persist_object_store!
self.file = new_file
end
end
file
rescue => e
# in case of failure delete new file
new_file.delete unless new_file.nil?
# revert back to the old file
self.object_store = from_object_store
self.file = file_to_delete
raise e
end
end
end
......@@ -29,7 +29,7 @@ shared_examples "migrates" do |to_store:, from_store: nil|
elsif from == described_class::Store::LOCAL
expect(subject.file).to be_a(CarrierWave::SanitizedFile)
else
raise 'Enexpected file type'
raise 'Unexpected file type'
end
end
......@@ -70,16 +70,16 @@ shared_examples "migrates" do |to_store:, from_store: nil|
end
context 'when migrate! is oqqupied by another process' do
let(:exclusive_lease_key) { "object_storage_migrate:#{subject.store_path}" }
let(:exclusive_lease_key) { "object_storage_migrate:#{subject.model.class}:#{subject.model.id}" }
before do
@uuid = Gitlab::ExclusiveLease.new(exclusive_lease_key, timeout: 1.hour.to_i).try_obtain
end
it 'does not execute migrate!' do
expect(subject).not_to receive(:object_store=)
expect(subject).not_to receive(:unsafe_migrate!)
migrate(to)
expect { migrate(to) }.to raise_error('Already running')
end
after do
......
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