diff options
author | Gabriel Mazetto <brodock@gmail.com> | 2017-11-15 14:42:38 +0100 |
---|---|---|
committer | Gabriel Mazetto <brodock@gmail.com> | 2017-11-17 10:11:31 +0100 |
commit | 516b6e8d7fa2c5964d6bab274b4d137026c72af7 (patch) | |
tree | 53fca6846e2ce962dc31634ea31ee9a973fbdc65 | |
parent | 95d9f82454c713a9151505f13a297e82cd591523 (diff) | |
download | gitlab-ce-hashed-storage-attachments-migration-path.tar.gz |
WIP Attachments migrationhashed-storage-attachments-migration-path
3 files changed, 100 insertions, 1 deletions
diff --git a/app/services/projects/hashed_storage/migrate_attachments_service.rb b/app/services/projects/hashed_storage/migrate_attachments_service.rb new file mode 100644 index 00000000000..1396c3a5c3c --- /dev/null +++ b/app/services/projects/hashed_storage/migrate_attachments_service.rb @@ -0,0 +1,54 @@ +module Projects + module HashedStorage + class MigrateAttachmentsService < BaseService + attr_reader :logger + + BATCH_SIZE = 500 + + def initialize(project, logger) + @project = project + @logger = logger + end + + def execute + project_before_migration = project.dup + project.storage_version = ::Project::HASHED_STORAGE_FEATURES[:attachments] + + project.uploads.find_each(batch_size: BATCH_SIZE) do |upload| + old_path = attachments_path(project_before_migration, upload) + new_path = attachments_path(project, upload) + move_attachment(old_path, new_path) + end + + project.save! + end + + private + + def attachments_path(project, upload) + File.join( + FileUploader.dynamic_path_segment(project), + upload.path + ) + end + + def move_attachment(old_path, new_path) + unless File.file?(old_path) + logger.error("Failed to migrate attachment from '#{old_path}' to '#{new_path}', source file doesn't exist (PROJECT_ID=#{project.id})") + return + end + + # Create attachments folder if doesn't exist yet + Dir.mkdir(File.dirname(new_path)) unless Dir.exist?(File.dirname(new_path)) + + if File.file?(new_path) + logger.info("Skipped attachment migration from '#{old_path}' to '#{new_path}', target file already exist (PROJECT_ID=#{project.id})") + return + end + + FileUtils.mv(old_path, new_path) + logger.info("Migrated project attachment from '#{old_path}' to '#{new_path}' (PROJECT_ID=#{project.id})") + end + end + end +end diff --git a/app/services/projects/hashed_storage_migration_service.rb b/app/services/projects/hashed_storage_migration_service.rb index b61f71cf9a0..662702c1db5 100644 --- a/app/services/projects/hashed_storage_migration_service.rb +++ b/app/services/projects/hashed_storage_migration_service.rb @@ -1,7 +1,7 @@ module Projects class HashedStorageMigrationService < BaseService attr_reader :logger - + def initialize(project, logger = nil) @project = project @logger = logger || Rails.logger @@ -12,6 +12,11 @@ module Projects unless project.hashed_storage?(:repository) return unless HashedStorage::MigrateRepositoryService.new(project, logger).execute end + + # Migrate attachments from Legacy to Hashed Storage + unless project.hashed_storage?(:attachments) + HashedStorage::MigrateAttachmentsService.new(project, logger).execute + end end end end diff --git a/spec/services/projects/hashed_storage_migration_service_spec.rb b/spec/services/projects/hashed_storage_migration_service_spec.rb new file mode 100644 index 00000000000..28b6daf217e --- /dev/null +++ b/spec/services/projects/hashed_storage_migration_service_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe Projects::HashedStorageMigrationService do + let(:project) { create(:project, :empty_repo, :wiki_repo) } + subject(:service) { described_class.new(project) } + + describe '#execute' do + context 'repository migration' do + it 'delegates migration to Projects::HashedStorage::MigrateRepositoryService' do + expect(Projects::HashedStorage::MigrateRepositoryService).to receive(:new).with(project, subject.logger).and_call_original + expect_any_instance_of(Projects::HashedStorage::MigrateRepositoryService).to receive(:execute) + + service.execute + end + + it 'does not delegate migration if repository is already migrated' do + project.storage_version = ::Project::LATEST_STORAGE_VERSION + expect_any_instance_of(Projects::HashedStorage::MigrateRepositoryService).not_to receive(:execute) + + service.execute + end + end + + context 'attachments migration' do + it 'delegates migration to Projects::HashedStorage::MigrateRepositoryService' do + expect(Projects::HashedStorage::MigrateAttachmentsService).to receive(:new).with(project, subject.logger).and_call_original + expect_any_instance_of(Projects::HashedStorage::MigrateAttachmentsService).to receive(:execute) + + service.execute + end + + it 'does not delegate migration if attachments are already migrated' do + project.storage_version = ::Project::LATEST_STORAGE_VERSION + expect_any_instance_of(Projects::HashedStorage::MigrateAttachmentsService).not_to receive(:execute) + + service.execute + end + end + end +end |