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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
# frozen_string_literal: true
module Ci
class Partition < Ci::ApplicationRecord
MAX_PARTITION_SIZE = 100.gigabytes
INITIAL_PARTITION_VALUE = 100
LATEST_PARTITION_VALUE = 102
DEFAULT_PARTITION_VALUES = (INITIAL_PARTITION_VALUE..LATEST_PARTITION_VALUE).to_a.freeze
validates :id, :status, presence: true
validates :status, uniqueness: { if: ->(partition) { partition.status_changed? && partition.current? } }
state_machine :status, initial: :preparing do
state :preparing, value: 0
state :ready, value: 1
state :current, value: 2
state :active, value: 3
event :ready do
transition preparing: :ready
end
event :switch_writes do
transition ready: :current
end
before_transition [:ready] => :current do
Ci::Partition.with_status(:current).update_all(status: Ci::Partition.statuses[:active])
end
end
scope :id_after, ->(partition_id) { where(arel_table[:id].gt(partition_id)) }
class << self
def statuses
@statuses ||= state_machines[:status].states.to_h { |state| [state.name, state.value] }.freeze
end
def current
with_status(:current).first
end
def create_next!
create!(id: last.id.next, status: statuses[:preparing])
end
def next_available(partition_id)
Ci::Partition
.with_status(:ready)
.id_after(partition_id)
.order(id: :asc)
.first
end
def provisioning(partition_id)
Ci::Partition
.with_status(:preparing)
.id_after(partition_id)
.order(id: :asc)
.first
end
end
def above_threshold?(threshold)
with_ci_connection do
Gitlab::Database::PostgresPartition
.with_parent_tables(parent_table_names)
.with_list_constraint(id)
.above_threshold(threshold)
.exists?
end
end
def all_partitions_exist?
with_ci_connection do
Gitlab::Database::PostgresPartition
.with_parent_tables(parent_table_names)
.with_list_constraint(id)
.count == parent_table_names.size
end
end
private
def with_ci_connection(&block)
Gitlab::Database::SharedModel.using_connection(connection, &block)
end
def parent_table_names
Ci::Partitionable.registered_models.map(&:table_name)
end
end
end
|