Commit 4407bcd2 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch 'improve-file_registry_removal_service' into 'master'

Refactoring FileRegistryRemoval service  and specs

See merge request gitlab-org/gitlab!77539
parents cf96c74e a533ce2d
# frozen_string_literal: true # frozen_string_literal: true
module Geo module Geo
##
## Geo::FileRegistryRemovalService handles blob removal from a secondary node,
## the file itself and the database records.
## It handles all the possible combinations of 4 variables:
## * Whether Model record exists
## * Whether Registry Record exists
## * Whether the file on a storage exists
## * Whether the file_path is passed (RegistryConsistencyWorker doesn't pass one)
## In all the cases the best effort should have to be made.
##
class FileRegistryRemovalService < BaseFileService class FileRegistryRemovalService < BaseFileService
include ::Gitlab::Utils::StrongMemoize include ::Gitlab::Utils::StrongMemoize
...@@ -73,16 +83,10 @@ module Geo ...@@ -73,16 +83,10 @@ module Geo
end end
end end
def blob_path_from_replicator
replicator.blob_path
rescue ActiveRecord::RecordNotFound
nil
end
def file_path def file_path
strong_memoize(:file_path) do strong_memoize(:file_path) do
next @object_file_path if @object_file_path next @object_file_path if @object_file_path
next blob_path_from_replicator if replicator
# When local storage is used, just rely on the existing methods # When local storage is used, just rely on the existing methods
next if file_uploader.nil? next if file_uploader.nil?
next file_uploader.file.path if file_uploader.object_store == ObjectStorage::Store::LOCAL next file_uploader.file.path if file_uploader.object_store == ObjectStorage::Store::LOCAL
...@@ -93,6 +97,8 @@ module Geo ...@@ -93,6 +97,8 @@ module Geo
def file_uploader def file_uploader
strong_memoize(:file_uploader) do strong_memoize(:file_uploader) do
next replicator.carrierwave_uploader if replicator
case object_type case object_type
when :job_artifact when :job_artifact
Ci::JobArtifact.find(object_db_id).file Ci::JobArtifact.find(object_db_id).file
......
...@@ -21,6 +21,7 @@ RSpec.describe Geo::FileRegistryRemovalService, :geo do ...@@ -21,6 +21,7 @@ RSpec.describe Geo::FileRegistryRemovalService, :geo do
described_class.new(:lfs, 99).execute described_class.new(:lfs, 99).execute
end end
context 'with job artifact' do
shared_examples 'removes artifact' do shared_examples 'removes artifact' do
subject(:service) { described_class.new('job_artifact', registry.artifact_id) } subject(:service) { described_class.new('job_artifact', registry.artifact_id) }
...@@ -57,42 +58,48 @@ RSpec.describe Geo::FileRegistryRemovalService, :geo do ...@@ -57,42 +58,48 @@ RSpec.describe Geo::FileRegistryRemovalService, :geo do
end end
end end
shared_examples 'removes LFS object' do let!(:job_artifact) { create(:ci_job_artifact, :archive) }
subject(:service) { described_class.new('lfs', registry.lfs_object_id) } let!(:registry) { create(:geo_job_artifact_registry, artifact_id: job_artifact.id) }
let!(:file_path) { job_artifact.file.path }
it_behaves_like 'removes artifact'
context 'migrated to object storage' do
before do before do
stub_exclusive_lease("file_registry_removal_service:lfs:#{registry.lfs_object_id}", job_artifact.update_column(:file_store, ObjectStorage::Store::REMOTE)
timeout: Geo::FileRegistryRemovalService::LEASE_TIMEOUT)
end end
it 'file from disk' do context 'with object storage enabled' do
expect do before do
service.execute stub_artifacts_object_storage
end.to change { File.exist?(file_path) }.from(true).to(false)
end end
it 'deletes registry entry' do it_behaves_like 'removes artifact'
expect do
service.execute
end.to change(Geo::LfsObjectRegistry, :count).by(-1)
end end
context 'with object storage disabled' do
before do
stub_artifacts_object_storage(enabled: false)
end end
shared_examples 'removes LFS object registry' do it_behaves_like 'removes artifact registry'
subject(:service) { described_class.new('lfs', registry.lfs_object_id) } end
end
context 'no job artifact record' do
before do before do
stub_exclusive_lease("file_registry_removal_service:lfs:#{registry.lfs_object_id}", job_artifact.delete
timeout: Geo::FileRegistryRemovalService::LEASE_TIMEOUT)
end end
it 'deletes registry entry' do it_behaves_like 'removes artifact' do
expect do subject(:service) { described_class.new('job_artifact', registry.artifact_id, file_path) }
service.execute end
end.to change(Geo::LfsObjectRegistry, :count).by(-1)
it_behaves_like 'removes artifact registry'
end end
end end
context 'with package file' do
shared_examples 'removes package file' do shared_examples 'removes package file' do
subject(:service) { described_class.new('package_file', registry.package_file_id) } subject(:service) { described_class.new('package_file', registry.package_file_id) }
...@@ -129,118 +136,108 @@ RSpec.describe Geo::FileRegistryRemovalService, :geo do ...@@ -129,118 +136,108 @@ RSpec.describe Geo::FileRegistryRemovalService, :geo do
end end
end end
context 'with job artifact' do let(:package_file) { create(:package_file_with_file) }
let!(:job_artifact) { create(:ci_job_artifact, :archive) } let!(:registry) { create(:geo_package_file_registry, package_file: package_file) }
let!(:registry) { create(:geo_job_artifact_registry, artifact_id: job_artifact.id) } let(:file_path) { package_file.file.path }
let!(:file_path) { job_artifact.file.path }
it_behaves_like 'removes artifact' it_behaves_like 'removes package file'
context 'migrated to object storage' do context 'no package file record' do
before do before do
stub_artifacts_object_storage package_file.delete
job_artifact.update_column(:file_store, JobArtifactUploader::Store::REMOTE)
end
it_behaves_like 'removes artifact'
end end
context 'migrated to object storage' do it_behaves_like 'removes package file' do
before do subject(:service) { described_class.new('package_file', registry.package_file_id, file_path) }
stub_artifacts_object_storage
job_artifact.update_column(:file_store, LfsObjectUploader::Store::REMOTE)
end end
context 'with object storage enabled' do
it_behaves_like 'removes artifact'
end end
context 'with object storage disabled' do context 'with orphaned registry' do
before do before do
stub_artifacts_object_storage(enabled: false) package_file.delete
end end
it_behaves_like 'removes artifact registry' it_behaves_like 'removes package file registry' do
subject(:service) { described_class.new('package_file', registry.package_file_id) }
end end
end end
context 'no job artifact record' do
before do
job_artifact.delete
end end
it_behaves_like 'removes artifact' do context 'with uploads' do
subject(:service) { described_class.new('job_artifact', registry.artifact_id, file_path) } shared_examples 'removes upload' do
end subject(:service) { described_class.new('upload', registry.file_id, file_path) }
end
context 'with orphaned registry' do
before do before do
job_artifact.delete stub_exclusive_lease("file_registry_removal_service:upload:#{registry.file_id}",
timeout: Geo::FileRegistryRemovalService::LEASE_TIMEOUT)
end end
it_behaves_like 'removes artifact registry' do it 'file from disk' do
subject(:service) { described_class.new('job_artifact', registry.artifact_id) } expect do
service.execute
end.to change { File.exist?(file_path) }.from(true).to(false)
end end
it 'deletes registry entry' do
expect do
service.execute
end.to change(Geo::UploadRegistry, :count).by(-1)
end end
end end
context 'with package file' do shared_examples 'removes upload registry' do
let(:package_file) { create(:package_file_with_file) } subject(:service) { described_class.new('upload', registry.file_id, file_path) }
let!(:registry) { create(:geo_package_file_registry, package_file: package_file) }
let(:file_path) { Tempfile.new.path }
before do before do
allow_next_instance_of(Geo::PackageFileReplicator) do |replicator| stub_exclusive_lease("file_registry_removal_service:upload:#{registry.file_id}",
allow(replicator).to receive(:blob_path).and_return(file_path) timeout: Geo::FileRegistryRemovalService::LEASE_TIMEOUT)
end
it 'deletes registry entry' do
expect do
service.execute
end.to change(Geo::UploadRegistry, :count).by(-1)
end end
end end
it_behaves_like 'removes package file' let!(:upload) { create(:upload, :with_file) }
let!(:registry) { create(:geo_upload_registry, file_id: upload.id) }
let!(:file_path) { upload.retrieve_uploader.file.path }
context 'no package file record' do it_behaves_like 'removes upload'
context 'migrated to object storage' do
before do before do
package_file.delete upload.update_column(:store, ObjectStorage::Store::REMOTE)
end end
it_behaves_like 'removes package file' do context 'with object storage enabled' do
subject(:service) { described_class.new('package_file', registry.package_file_id, file_path) } before do
stub_uploads_object_storage(AvatarUploader)
end end
it_behaves_like 'removes upload'
end end
context 'with orphaned registry' do context 'with object storage disabled' do
before do before do
package_file.delete stub_uploads_object_storage(AvatarUploader, enabled: false)
end end
it_behaves_like 'removes package file registry' do it_behaves_like 'removes upload registry'
subject(:service) { described_class.new('package_file', registry.package_file_id) }
end end
end end
end
context 'with uploads' do
let!(:upload) { create(:user, :with_avatar).avatar.upload }
let!(:registry) { create(:geo_upload_registry, file_id: upload.id) }
let!(:file_path) { upload.retrieve_uploader.file.path }
subject(:service) { described_class.new('upload', registry.file_id) }
context 'no upload record' do
before do before do
stub_exclusive_lease("file_registry_removal_service:upload:#{registry.file_id}", upload.delete
timeout: Geo::FileRegistryRemovalService::LEASE_TIMEOUT)
end end
it 'file from disk' do it_behaves_like 'removes upload' do
expect do subject(:service) { described_class.new('upload', registry.file_id, file_path) }
service.execute
end.to change { File.exist?(file_path) }.from(true).to(false)
end end
it 'deletes registry entry' do it_behaves_like 'removes upload registry'
expect do
service.execute
end.to change(Geo::UploadRegistry, :count).by(-1)
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