diff options
Diffstat (limited to 'app/models/project_authorization.rb')
-rw-r--r-- | app/models/project_authorization.rb | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb index 5c6fdec16ca..8b43e5e5d63 100644 --- a/app/models/project_authorization.rb +++ b/app/models/project_authorization.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true class ProjectAuthorization < ApplicationRecord + BATCH_SIZE = 1000 + SLEEP_DELAY = 0.1 + extend SuppressCompositePrimaryKeyWarning include FromUnion @@ -26,11 +29,45 @@ class ProjectAuthorization < ApplicationRecord super(attributes, unique_by: connection.schema_cache.primary_keys(table_name)) end - def self.insert_all_in_batches(attributes, per_batch = 1000) + def self.insert_all_in_batches(attributes, per_batch = BATCH_SIZE) + add_delay = add_delay_between_batches?(entire_size: attributes.size, batch_size: per_batch) + attributes.each_slice(per_batch) do |attributes_batch| insert_all(attributes_batch) + perform_delay if add_delay + end + end + + def self.delete_all_in_batches_for_project(project:, user_ids:, per_batch: BATCH_SIZE) + add_delay = add_delay_between_batches?(entire_size: user_ids.size, batch_size: per_batch) + + user_ids.each_slice(per_batch) do |user_ids_batch| + project.project_authorizations.where(user_id: user_ids_batch).delete_all + perform_delay if add_delay + end + end + + def self.delete_all_in_batches_for_user(user:, project_ids:, per_batch: BATCH_SIZE) + add_delay = add_delay_between_batches?(entire_size: project_ids.size, batch_size: per_batch) + + project_ids.each_slice(per_batch) do |project_ids_batch| + user.project_authorizations.where(project_id: project_ids_batch).delete_all + perform_delay if add_delay end end + + private_class_method def self.add_delay_between_batches?(entire_size:, batch_size:) + # The reason for adding a delay is to give the replica database enough time to + # catch up with the primary when large batches of records are being added/removed. + # Hance, we add a delay only if the GitLab installation has a replica database configured. + entire_size > batch_size && + !::Gitlab::Database::LoadBalancing.primary_only? && + Feature.enabled?(:enable_minor_delay_during_project_authorizations_refresh) + end + + private_class_method def self.perform_delay + sleep(SLEEP_DELAY) + end end ProjectAuthorization.prepend_mod_with('ProjectAuthorization') |