diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-18 13:50:51 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-18 13:50:51 +0300 |
commit | db384e6b19af03b4c3c82a5760d83a3fd79f7982 (patch) | |
tree | 34beaef37df5f47ccbcf5729d7583aae093cffa0 /app/models/batched_git_ref_updates/deletion.rb | |
parent | 54fd7b1bad233e3944434da91d257fa7f63c3996 (diff) |
Add latest changes from gitlab-org/gitlab@16-3-stable-eev16.3.0-rc42
Diffstat (limited to 'app/models/batched_git_ref_updates/deletion.rb')
-rw-r--r-- | app/models/batched_git_ref_updates/deletion.rb | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/app/models/batched_git_ref_updates/deletion.rb b/app/models/batched_git_ref_updates/deletion.rb new file mode 100644 index 00000000000..61bba8aeba9 --- /dev/null +++ b/app/models/batched_git_ref_updates/deletion.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +module BatchedGitRefUpdates + class Deletion < ApplicationRecord + PARTITION_DURATION = 1.day + + include IgnorableColumns + include BulkInsertSafe + include PartitionedTable + include EachBatch + + self.table_name = 'p_batched_git_ref_updates_deletions' + self.primary_key = :id + self.sequence_name = :to_be_deleted_git_refs_id_seq + + # This column must be ignored otherwise Rails will cache the default value and `bulk_insert!` will start saving + # incorrect partition_id. + ignore_column :partition_id, remove_with: '3000.0', remove_after: '3000-01-01' + + belongs_to :project, inverse_of: :to_be_deleted_git_refs + + scope :for_partition, ->(partition) { where(partition_id: partition) } + scope :for_project, ->(project_id) { where(project_id: project_id) } + scope :select_ref_and_identity, -> { select(:ref, :id, arel_table[:partition_id].as('partition')) } + + partitioned_by :partition_id, strategy: :sliding_list, + next_partition_if: ->(active_partition) do + oldest_record_in_partition = Deletion + .select(:id, :created_at) + .for_partition(active_partition.value) + .order(:id) + .limit(1) + .take + + oldest_record_in_partition.present? && + oldest_record_in_partition.created_at < PARTITION_DURATION.ago + end, + detach_partition_if: ->(partition) do + !Deletion + .for_partition(partition.value) + .status_pending + .exists? + end + + enum status: { pending: 1, processed: 2 }, _prefix: :status + + def self.mark_records_processed(records) + update_by_partition(records) do |partitioned_scope| + partitioned_scope.update_all(status: :processed) + end + end + + # Your scope must select_ref_and_identity before calling this method as it relies on partition being explicitly + # selected + def self.update_by_partition(records) + records.group_by(&:partition).each do |partition, records_within_partition| + partitioned_scope = status_pending + .for_partition(partition) + .where(id: records_within_partition.map(&:id)) + + yield(partitioned_scope) + end + end + + private_class_method :update_by_partition + end +end |