summaryrefslogtreecommitdiff
path: root/spec/workers/git_garbage_collect_worker_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/workers/git_garbage_collect_worker_spec.rb')
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb137
1 files changed, 112 insertions, 25 deletions
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
index cb6396e2859..223f5aea813 100644
--- a/spec/workers/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/git_garbage_collect_worker_spec.rb
@@ -7,35 +7,61 @@ require 'spec_helper'
RSpec.describe GitGarbageCollectWorker do
include GitHelpers
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
let(:shell) { Gitlab::Shell.new }
let!(:lease_uuid) { SecureRandom.uuid }
let!(:lease_key) { "project_housekeeping:#{project.id}" }
+ let(:params) { [project.id, task, lease_key, lease_uuid] }
subject { described_class.new }
+ shared_examples 'it calls Gitaly' do
+ specify do
+ expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(gitaly_task)
+ .and_return(nil)
+
+ subject.perform(*params)
+ end
+ end
+
+ shared_examples 'it updates the project statistics' do
+ specify do
+ expect_any_instance_of(Projects::UpdateStatisticsService).to receive(:execute).and_call_original
+ expect(Projects::UpdateStatisticsService)
+ .to receive(:new)
+ .with(project, nil, statistics: [:repository_size, :lfs_objects_size])
+ .and_call_original
+
+ subject.perform(*params)
+ end
+ end
+
describe "#perform" do
+ let(:gitaly_task) { :garbage_collect }
+ let(:task) { :gc }
+
context 'with active lease_uuid' do
before do
allow(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
end
+ it_behaves_like 'it calls Gitaly'
+ it_behaves_like 'it updates the project statistics'
+
it "flushes ref caches when the task if 'gc'" do
expect(subject).to receive(:renew_lease).with(lease_key, lease_uuid).and_call_original
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect)
- .and_return(nil)
expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original
expect_any_instance_of(Repository).to receive(:branch_names).and_call_original
expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original
expect_any_instance_of(Gitlab::Git::Repository).to receive(:has_visible_content?).and_call_original
- subject.perform(project.id, :gc, lease_key, lease_uuid)
+ subject.perform(*params)
end
it 'handles gRPC errors' do
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect).and_raise(GRPC::NotFound)
- expect { subject.perform(project.id, :gc, lease_key, lease_uuid) }.to raise_exception(Gitlab::Git::Repository::NoRepository)
+ expect { subject.perform(*params) }.to raise_exception(Gitlab::Git::Repository::NoRepository)
end
end
@@ -49,11 +75,13 @@ RSpec.describe GitGarbageCollectWorker do
expect_any_instance_of(Repository).not_to receive(:branch_names).and_call_original
expect_any_instance_of(Repository).not_to receive(:has_visible_content?).and_call_original
- subject.perform(project.id, :gc, lease_key, lease_uuid)
+ subject.perform(*params)
end
end
context 'with no active lease' do
+ let(:params) { [project.id] }
+
before do
allow(subject).to receive(:get_lease_uuid).and_return(false)
end
@@ -63,15 +91,17 @@ RSpec.describe GitGarbageCollectWorker do
allow(subject).to receive(:try_obtain_lease).and_return(SecureRandom.uuid)
end
+ it_behaves_like 'it calls Gitaly'
+ it_behaves_like 'it updates the project statistics'
+
it "flushes ref caches when the task if 'gc'" do
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect)
- .and_return(nil)
+ expect(subject).to receive(:get_lease_uuid).with("git_gc:#{task}:#{project.id}").and_return(false)
expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original
expect_any_instance_of(Repository).to receive(:branch_names).and_call_original
expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original
expect_any_instance_of(Gitlab::Git::Repository).to receive(:has_visible_content?).and_call_original
- subject.perform(project.id)
+ subject.perform(*params)
end
context 'when the repository has joined a pool' do
@@ -81,7 +111,57 @@ RSpec.describe GitGarbageCollectWorker do
it 'ensures the repositories are linked' do
expect_any_instance_of(PoolRepository).to receive(:link_repository).once
- subject.perform(project.id)
+ subject.perform(*params)
+ end
+ end
+
+ context 'LFS object garbage collection' do
+ before do
+ stub_lfs_setting(enabled: true)
+ end
+
+ let_it_be(:lfs_reference) { create(:lfs_objects_project, project: project) }
+ let(:lfs_object) { lfs_reference.lfs_object }
+
+ context 'with cleanup_lfs_during_gc feature flag enabled' do
+ before do
+ stub_feature_flags(cleanup_lfs_during_gc: true)
+ end
+
+ it 'cleans up unreferenced LFS objects' do
+ expect_next_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences) do |svc|
+ expect(svc.project).to eq(project)
+ expect(svc.dry_run).to be_falsy
+ expect(svc).to receive(:run!).and_call_original
+ end
+
+ subject.perform(*params)
+
+ expect(project.lfs_objects.reload).not_to include(lfs_object)
+ end
+
+ it 'does nothing if the database is read-only' do
+ expect(Gitlab::Database).to receive(:read_only?) { true }
+ expect_any_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences).not_to receive(:run!)
+
+ subject.perform(*params)
+
+ expect(project.lfs_objects.reload).to include(lfs_object)
+ end
+ end
+
+ context 'with cleanup_lfs_during_gc feature flag disabled' do
+ before do
+ stub_feature_flags(cleanup_lfs_during_gc: false)
+ end
+
+ it 'does not clean up unreferenced LFS objects' do
+ expect_any_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences).not_to receive(:run!)
+
+ subject.perform(*params)
+
+ expect(project.lfs_objects.reload).to include(lfs_object)
+ end
end
end
end
@@ -97,48 +177,55 @@ RSpec.describe GitGarbageCollectWorker do
expect_any_instance_of(Repository).not_to receive(:branch_names).and_call_original
expect_any_instance_of(Repository).not_to receive(:has_visible_content?).and_call_original
- subject.perform(project.id)
+ subject.perform(*params)
end
end
end
context "repack_full" do
+ let(:task) { :full_repack }
+ let(:gitaly_task) { :repack_full }
+
before do
expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
end
- it "calls Gitaly" do
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:repack_full)
- .and_return(nil)
-
- subject.perform(project.id, :full_repack, lease_key, lease_uuid)
- end
+ it_behaves_like 'it calls Gitaly'
+ it_behaves_like 'it updates the project statistics'
end
context "pack_refs" do
+ let(:task) { :pack_refs }
+ let(:gitaly_task) { :pack_refs }
+
before do
expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
end
it "calls Gitaly" do
- expect_any_instance_of(Gitlab::GitalyClient::RefService).to receive(:pack_refs)
+ expect_any_instance_of(Gitlab::GitalyClient::RefService).to receive(task)
.and_return(nil)
- subject.perform(project.id, :pack_refs, lease_key, lease_uuid)
+ subject.perform(*params)
+ end
+
+ it 'does not update the project statistics' do
+ expect(Projects::UpdateStatisticsService).not_to receive(:new)
+
+ subject.perform(*params)
end
end
context "repack_incremental" do
+ let(:task) { :incremental_repack }
+ let(:gitaly_task) { :repack_incremental }
+
before do
expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
end
- it "calls Gitaly" do
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:repack_incremental)
- .and_return(nil)
-
- subject.perform(project.id, :incremental_repack, lease_key, lease_uuid)
- end
+ it_behaves_like 'it calls Gitaly'
+ it_behaves_like 'it updates the project statistics'
end
shared_examples 'gc tasks' do