Add advisory lock to ensure uniqueness of LFS objects projects

What does this MR do and why?

We want to deduplicate the lfs_objects_projects table by lfs_object_id, project_id, and repository_type. To achieve this, we have !154323 (merged), which creates a batched background migration. However, during the deduplication, we should also avoid creating new duplicates in the lfs_objects_projects table.

This MR introduces an explicit locking mechanism (advisory lock) in the lfs_object_project model, executed on every record creation (except bulk insert, which is not likely the source for duplications). A new callback will take this advisory lock and affect the 3 column values if they are present. Also, this callback is behind an FF to ensure its effectiveness and behavior while we perform a gradual rollout.

Context: !154323 (comment 1994629812)

MR acceptance checklist

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

How to set up and validate locally

Example below:

  1. In the rails console, enable the ensure_lfs_object_project_uniqueness FF.
    Feature.enable(:ensure_lfs_object_project_uniqueness)
  2. Start 2 Rails console
    • In the first console:
       ActiveRecord::Base.transaction do
         FactoryBot.create(:lfs_objects_project, project: Project.last) 
         sleep 50 # so we can write things in the 2nd console 
       end
    • In the second console:
         FactoryBot.create(:lfs_objects_project, project: Project.last, lfs_object_id: COPY_IT_FROM_CONSOLE1_INSERT_STATEMENT)
  3. The command in the 2nd console command should be blocked for <50 seconds and eventually fail with a validation error.

Related to #199909 (closed)

Edited by Javiera Tapia

Merge request reports

Loading