Previously a lease would only be obtained to update data. This could
lead to duplicate data being inserted, triggering a UNIQUE constraint
error. To work around this we now acquire a lease before performing
_any_ project authorization work, releasing it at the very end.
Fixes#25987
This column used to be a 32 bits integer, allowing for only a maximum of
2 147 483 647 rows. Given enough users one can hit this limit pretty
quickly, as was the case for GitLab.com.
Changing this type to bigint (= 64 bits) would give us more space, but
we'd eventually hit the same limit given enough users and projects. A
much more sustainable solution is to simply drop the "id" column.
There were only 2 lines of code depending on this column being present,
and neither truly required it to be present. Instead the code now uses
the "project_id" column combined with the "user_id" column. This means
that instead of something like this:
DELETE FROM project_authorizations
WHERE user_id = X
AND id = Y;
We now run the following when removing rows:
DELETE FROM project_authorizations
WHERE user_id = X
AND project_id = Y;
Since both user_id and project_id are indexed this should not slow down
the DELETE query.
This commit also removes the "dependent: destroy" clause from the
"project_authorizations" relation in the User and Project models.
Keeping this prevents Rails from being able to remove data as it relies
on an "id" column being present. Since the "project_authorizations"
table has proper foreign keys set up (with cascading removals) we don't
need to depend on any Rails logic.
Prior to this commit the refreshing of authorized projects was done in
two steps:
1. Remove existing authorizations
2. Insert a new list of all authorizations
This can lead to a high amount of dead tuples as every time all rows are
being replaced. For example, if a user with 100 authorizations is given
access to a new project this would lead to:
* 100 rows being removed
* 101 new rows being inserted
This commit changes the way this system works so it only removes/inserts
what is necessary. Using the above example this would lead to only 1 new
row being inserted, with the initial 100 being left untouched.
Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/25257