1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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_never: true
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
|