Skip to content
Snippets Groups Projects
Commit 58134cbb authored by Vasilii Iakliushin's avatar Vasilii Iakliushin :two:
Browse files

Destroy merge request diffs in batches

Contributes to #352511

**Problem**

Project delete causes a timeout error, because of `DELETE FROM projects`
query.

**Solution**

Extract `merge_request_diffs` deletion process into a separate
statement.
parent 439ca344
No related branches found
No related tags found
1 merge request!96455Destroy merge request diffs in batches
......@@ -134,6 +134,8 @@ def destroy_project_related_records(project)
destroy_ci_records!
destroy_mr_diff_relations!
destroy_merge_request_diffs! if ::Feature.enabled?(:extract_mr_diff_deletions)
# Rails attempts to load all related records into memory before
# destroying: https://github.com/rails/rails/issues/22510
# This ensures we delete records in batches.
......@@ -180,6 +182,24 @@ def destroy_mr_diff_relations!
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def destroy_merge_request_diffs!
mr_batch_size = 100
delete_batch_size = 1000
project.merge_requests.each_batch(column: :iid, of: mr_batch_size) do |relation_ids|
loop do
deleted_rows = MergeRequestDiff
.where(merge_request_id: relation_ids)
.limit(delete_batch_size)
.delete_all
break if deleted_rows == 0
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
def destroy_ci_records!
# Make sure to destroy this first just in case the project is undergoing stats refresh.
# This is to avoid logging the artifact deletion in Ci::JobArtifacts::DestroyBatchService.
......
---
name: extract_mr_diff_deletions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96455
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372060
milestone: '15.4'
type: development
group: group::source code
default_enabled: false
......@@ -135,6 +135,33 @@
end
end
context 'deleting a project with merge request diffs' do
let!(:merge_request) { create(:merge_request, source_project: project) }
let!(:another_project_mr) { create(:merge_request, source_project: create(:project)) }
it 'deletes merge request diffs' do
merge_request_diffs = merge_request.merge_request_diffs
expect(merge_request_diffs.size).to eq(1)
expect { destroy_project(project, user, {}) }.to change(MergeRequestDiff, :count).by(-1)
expect { another_project_mr.reload }.not_to raise_error
end
context 'when extract_mr_diff_deletions feature flag is disabled' do
before do
stub_feature_flags(extract_mr_diff_deletions: false)
end
it 'also deletes merge request diffs' do
merge_request_diffs = merge_request.merge_request_diffs
expect(merge_request_diffs.size).to eq(1)
expect { destroy_project(project, user, {}) }.to change(MergeRequestDiff, :count).by(-1)
expect { another_project_mr.reload }.not_to raise_error
end
end
end
it_behaves_like 'deleting the project'
it 'invalidates personal_project_count cache' do
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment