Skip to content

Draft: Direct reassign placeholder process

Direct Reassignment for Placeholder Users (Proof of Concept)

This merge request introduces a proof of concept for a new "direct reassignment" feature that allows placeholder user records to be reassigned without relying on placeholder references.

This reassignment works because each placeholder user is uniquely linked to a single import source user record. In other words, all contributions assigned to a placeholder user belong to one "external" user.

Note that this does not apply when contributions are assigned to the Import User type. Contributions assigned to this type can belong to different "external" users, and the placeholder reference table is responsible for storing which contributions belong to each "external" user.

What Changed

  • Introduces a DirectReassign class that updates record ownership directly by querying user_id columns, bypassing the need for placeholder references. Technically, the class performs queries like:

      UPDATE "notes" SET "author_id" = REASSIGNED_USER_ID WHERE ("notes"."id") IN (SELECT "notes"."id" FROM "notes" WHERE "notes"."author_id" = PLACEHOLDER_USER_USER LIMIT 500)

    Note that the SELECT query only uses the author_id column, making the query efficient.

    Also, this is the same approach used by Users::MigrateRecordsToGhostUserService to transfer contributions to the ghost user.

  • Implements a safelist of models/attributes that have proper database indexes, which allow the direct reassignment efficiently

  • For models/attributes not on the safelist, the process continues to create and use placeholder references

Feature flag

The update introduces two feature flags: one for enabling or disabling the Direct Reassign approach, and another for determining if references should be created. We will have to continue creating references until the Direct Reassign method is deemed safe to use. If it needs to be disabled due to a bug, the reassign process will revert to using placeholder references.

Probably the second feature flag will not be used. It will depend on how we decide to roll out the change.

Reassignment Scope

The implementation reassigns all records owned by a placeholder user, regardless of whether associated projects/groups have been transferred outside the original top-level namespace. This behavior is consistent with the existing reference-based approach.

While #472725 proposes scoping reassignments to only contributions that still belong to the top-level namespace, that will no longer be possible using the Direct Reassignment approach.

The primary reason is that we would need to add additional database indexes scoping the sharding key and user ID.

After careful review, I believe it's safe to continue reassigning all contributions, including those for transferred projects, since this change does not impact membership migrations. In other words, the reassignment process still does not create memberships for transferred groups and projects. Therefore, even if a user becomes the owner of a transferred contribution after reassignment, they will not be added as a member and will be unable to perform any actions.

Just to clarify the scenario, consider these steps:

  1. Project is imported into a top-level group.
  2. Project contributions are assigned to a placeholder user.
  3. The project is transferred to another top-level group.
  4. The group owner of the original top-level group reassigns the placeholder user to a different user.
  5. Contributions of the project, now belonging to a different top-level group, are reassigned.
  6. Memberships are NOT created for the project, since they no longer belong to the original top-level group.

References

#569779 (closed)

Screenshots or screen recordings

Before After

How to set up and validate locally

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Rodrigo Tomonari

Merge request reports

Loading