1# frozen_string_literal: true
2
3# This module handles backward compatibility for import/export of merge requests after
4# multiple assignees feature was introduced. Also, it handles the scenarios where
5# the #26496 background migration hasn't finished yet.
6# Ideally, most of this code should be removed at #59457.
7module DeprecatedAssignee
8  extend ActiveSupport::Concern
9
10  def assignee_ids=(ids)
11    nullify_deprecated_assignee
12    super
13  end
14
15  def assignees=(users)
16    nullify_deprecated_assignee
17    super
18  end
19
20  def assignee_id=(id)
21    self.assignee_ids = Array(id)
22  end
23
24  def assignee=(user)
25    self.assignees = Array(user)
26  end
27
28  def assignee
29    assignees.first
30  end
31
32  def assignee_id
33    assignee_ids.first
34  end
35
36  def assignee_ids
37    if Gitlab::Database.read_only? && pending_assignees_population?
38      return Array(deprecated_assignee_id)
39    end
40
41    update_assignees_relation
42    super
43  end
44
45  def assignees
46    if Gitlab::Database.read_only? && pending_assignees_population?
47      return User.where(id: deprecated_assignee_id)
48    end
49
50    update_assignees_relation
51    super
52  end
53
54  private
55
56  # This will make the background migration process quicker (#26496) as it'll have less
57  # assignee_id rows to look through.
58  def nullify_deprecated_assignee
59    return unless persisted? && Gitlab::Database.read_only?
60
61    update_column(:assignee_id, nil)
62  end
63
64  # This code should be removed in the clean-up phase of the
65  # background migration (#59457).
66  def pending_assignees_population?
67    persisted? && deprecated_assignee_id && merge_request_assignees.empty?
68  end
69
70  # If there's an assignee_id and no relation, it means the background
71  # migration at #26496 didn't reach this merge request yet.
72  # This code should be removed in the clean-up phase of the
73  # background migration (#59457).
74  def update_assignees_relation
75    if pending_assignees_population?
76      transaction do
77        merge_request_assignees.create!(user_id: deprecated_assignee_id, merge_request_id: id)
78        update_column(:assignee_id, nil)
79      end
80    end
81  end
82
83  def deprecated_assignee_id
84    read_attribute(:assignee_id)
85  end
86end
87