diff options
author | Yorick Peterse <yorickpeterse@gmail.com> | 2017-01-17 00:34:13 +0300 |
---|---|---|
committer | Yorick Peterse <yorickpeterse@gmail.com> | 2017-01-17 00:37:48 +0300 |
commit | 6f88984b0d935b5c39b063969c14204cf0a62362 (patch) | |
tree | 29d3ca6f3aeed57d366e473fee2f2b75ec30be7f /app/services/users | |
parent | 142be72a2aa6920fa60cc267737f2e702fdeae12 (diff) |
Synchronize all project authorization refreshing
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
Diffstat (limited to 'app/services/users')
-rw-r--r-- | app/services/users/refresh_authorized_projects_service.rb | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb index 21ec1bd9e65..2d211d5ebbe 100644 --- a/app/services/users/refresh_authorized_projects_service.rb +++ b/app/services/users/refresh_authorized_projects_service.rb @@ -26,8 +26,26 @@ module Users user.reload end - # This method returns the updated User object. def execute + lease_key = "refresh_authorized_projects:#{user.id}" + lease = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT) + + until uuid = lease.try_obtain + # Keep trying until we obtain the lease. If we don't do so we may end up + # not updating the list of authorized projects properly. To prevent + # hammering Redis too much we'll wait for a bit between retries. + sleep(1) + end + + begin + execute_without_lease + ensure + Gitlab::ExclusiveLease.cancel(lease_key, uuid) + end + end + + # This method returns the updated User object. + def execute_without_lease current = current_authorizations_per_project fresh = fresh_access_levels_per_project @@ -47,26 +65,7 @@ module Users end end - update_with_lease(remove, add) - end - - # Updates the list of authorizations using an exclusive lease. - def update_with_lease(remove = [], add = []) - lease_key = "refresh_authorized_projects:#{user.id}" - lease = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT) - - until uuid = lease.try_obtain - # Keep trying until we obtain the lease. If we don't do so we may end up - # not updating the list of authorized projects properly. To prevent - # hammering Redis too much we'll wait for a bit between retries. - sleep(1) - end - - begin - update_authorizations(remove, add) - ensure - Gitlab::ExclusiveLease.cancel(lease_key, uuid) - end + update_authorizations(remove, add) end # Updates the list of authorizations for the current user. |