summaryrefslogtreecommitdiff
path: root/lib/gitlab/background_migration/replace_blocked_by_links.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/background_migration/replace_blocked_by_links.rb')
-rw-r--r--lib/gitlab/background_migration/replace_blocked_by_links.rb19
1 files changed, 12 insertions, 7 deletions
diff --git a/lib/gitlab/background_migration/replace_blocked_by_links.rb b/lib/gitlab/background_migration/replace_blocked_by_links.rb
index 26626aaef79..0c29887bb00 100644
--- a/lib/gitlab/background_migration/replace_blocked_by_links.rb
+++ b/lib/gitlab/background_migration/replace_blocked_by_links.rb
@@ -12,14 +12,19 @@ module Gitlab
blocked_by_links = IssueLink.where(id: start_id..stop_id).where(link_type: 2)
ActiveRecord::Base.transaction do
- # if there is duplicit bi-directional relation (issue2 is blocked by issue1
- # and issue1 already links issue2), then we can just delete 'blocked by'.
- # This should be rare as we have a pre-create check which checks if issues are
- # already linked
- blocked_by_links
+ # There could be two edge cases:
+ # 1) issue1 is blocked by issue2 AND issue2 blocks issue1 (type 1)
+ # 2) issue1 is blocked by issue2 AND issue2 is related to issue1 (type 0)
+ # In both cases cases we couldn't convert blocked by relation to
+ # `issue2 blocks issue` because there is already a link with the same
+ # source/target id. To avoid these conflicts, we first delete any
+ # "opposite" links before we update `blocked by` relation. This
+ # should be rare as we have a pre-create check which checks if issues
+ # are already linked
+ opposite_ids = blocked_by_links
+ .select('opposite_links.id')
.joins('INNER JOIN issue_links as opposite_links ON issue_links.source_id = opposite_links.target_id AND issue_links.target_id = opposite_links.source_id')
- .where('opposite_links.link_type': 1)
- .delete_all
+ IssueLink.where(id: opposite_ids).delete_all
blocked_by_links.update_all('source_id=target_id,target_id=source_id,link_type=1')
end