User mapping - Create table to enable Import User reassignment
In the improved user mapping, to support the reassignment of contributions, we need a new table that correlates the imported resource, the original user and the placeholder user / import user. In this issue, we will create the table and model and update the Direct Transfer to store the information in the table.
In the POC, a table called import_details was created to serve this purpose. The table is similar to the one described in Option 1 below. However, we will be using Option 3.
As mentioned in the POC, the table structure of this new table could be modified to increase its flexibility. Here are two options:
Proposed approaches:
Option 1
Option 1 approach
Field name | Description |
---|---|
id | |
namespace_id | |
project_id | |
importable_type | Polymorphic Association. Class name (Example: MergeRequest, Issue, Epic, Note) |
importable_id | ID of the resource |
assignee_id | Import::SourceUser reference |
author_id | Import::SourceUser reference |
closed_by_id | Import::SourceUser reference |
created_by_id | Import::SourceUser reference |
last_edited_by_id | Import::SourceUser reference |
latest_closed_by_id | Import::SourceUser reference |
merge_user_id | Import::SourceUser reference |
merged_by_id | Import::SourceUser reference |
owner_id | Import::SourceUser reference |
resolved_by_id | Import::SourceUser reference |
updated_by_id | Import::SourceUser reference |
user_id | Import::SourceUser reference |
For this option, each imported resource would have a has_one
association with the new table. Only the relevant foreign key would be populated.
When dealing with merge requests, four associations with the user table need to be taken into account: resolved_by_id, author_id, updated_by_id, and last_edited_by_id. For each imported merge request, a row is saved in this table, and the foreign keys resolved_by_id, author_id, updated_by_id, and last_edited_by_id are populated with the ID of an Import::SourceUser.
Option 2
Option 2 approach
Create a new table similar to the structure below and define a has_many
association on all models that resources are imported.
Field name | Description |
---|---|
id | |
namespace_id | |
project_id | |
importable_type | Polymorphic Association. Class name (Example: MergeRequest, Issue, Epic, Note) |
importable_id | ID of the resource |
importable_foreign_key_name | Example: assignee_id, author_id, user_id |
import_source_id | Import::SourceUser reference |
For this option, each imported resource would have a has_many
association with the new table. When the imported resource references the user table multiple times, multiple rows are created.
Option 3
Create a table (or two tables) for all contributions that store the table_name
, import_source_user_id
and the primary keys of table_name
that need to be mapped (based on a discussion in another issue: #443556 (comment 1870409887)). This approach does not use FK constraints to each imported table, so if a record gets deleted before it can be reassigned, we can skip the association when iterating over the rows in this table for a given import_source_user
. The new table could look something like this:
table_name | import_source_users_id | primary_key* | user_reference | Mapped |
---|---|---|---|---|
issues_assignees | 100019 | {issue_id: 10, user_id: 20 } | user_id | FALSE |
merge_requests | 100019 | 1 | 'author_id' | FALSE |
merge_requests | 100019 | 1 | 'assignee_id' | FALSE |
notes | 100019 | 3 | 'author_id' | FALSE |
issues_assignees | 100027 | {issue_id: 10, user_id: 21 } | user_id | TRUE |
merge_requests | 100027 | 5 | 'author_id' | TRUE |
notes | 100027 | 5 | 'assignee_id` | TRUE |
Field name | Description |
---|---|
id | |
table_name | the record's table name that will need to be reassigned as a string |
import_source_users_id | id of the Import::SourceUser to map records to. It may be associated to an import user instead of a placeholder user |
primary_key | primary key of the <table_name> record that needs to be mapped. Some primary keys will be hashes for composite primary keys* |
user_reference | the column on <table_name>'s record that needs to be replaced with the import_source_user placeholder id. Some tables can have multiple belongs_to user references** |
Mapped | boolean of whether or not this record has been reassigned yet |
Notes:
* primary_key
could be normalized to a separate table keep this table from getting to big, or so that we can better enforce the data types of primary_key
** user_reference
is just to determine which user reference needs to be reassigned. To handle column name changes, we should have a YML file somewhere that can resolve the actual column name that needs to be updated.
Open questions
- What should be the table name?
Selected approach
Option 3
TASKS
- Create a new table
- Define the model
Update Direct Transfer to associate imported resources with the new model in case the contribution is assigned to the Import User.