Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/batched_git_ref_updates/deletion.rb')
-rw-r--r--app/models/batched_git_ref_updates/deletion.rb67
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