diff options
Diffstat (limited to 'app/services/batched_git_ref_updates/project_cleanup_service.rb')
-rw-r--r-- | app/services/batched_git_ref_updates/project_cleanup_service.rb | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/app/services/batched_git_ref_updates/project_cleanup_service.rb b/app/services/batched_git_ref_updates/project_cleanup_service.rb new file mode 100644 index 00000000000..f9518cad975 --- /dev/null +++ b/app/services/batched_git_ref_updates/project_cleanup_service.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module BatchedGitRefUpdates + class ProjectCleanupService + include ::Gitlab::ExclusiveLeaseHelpers + + LOCK_TIMEOUT = 10.minutes + GITALY_BATCH_SIZE = 100 + QUERY_BATCH_SIZE = 1000 + MAX_DELETES = 10_000 + + def initialize(project_id) + @project_id = project_id + end + + def execute + total_deletes = 0 + + in_lock("#{self.class}/#{@project_id}", retries: 0, ttl: LOCK_TIMEOUT) do + project = Project.find_by_id(@project_id) + break unless project + + Deletion + .status_pending + .for_project(@project_id) + .select_ref_and_identity + .each_batch(of: QUERY_BATCH_SIZE) do |batch| + refs = batch.map(&:ref) + + refs.each_slice(GITALY_BATCH_SIZE) do |refs_to_delete| + project.repository.delete_refs(*refs_to_delete) + end + + total_deletes += refs.count + Deletion.mark_records_processed(batch) + + break if total_deletes >= MAX_DELETES + end + end + + { total_deletes: total_deletes } + end + end +end |