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:
- In the rails console, enable the
ensure_lfs_object_project_uniquenessFF.Feature.enable(:ensure_lfs_object_project_uniqueness) - 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) - The command in the 2nd console command should be blocked for <50 seconds and eventually fail with a validation error.
Related to #199909 (closed)