74 lines
1.9 KiB
Ruby
74 lines
1.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Ci
|
|
##
|
|
# This module implements a way to set the `partion_id` value on a dependent
|
|
# resource from a parent record.
|
|
# Usage:
|
|
#
|
|
# class PipelineVariable < Ci::ApplicationRecord
|
|
# include Ci::Partitionable
|
|
#
|
|
# belongs_to :pipeline
|
|
# partitionable scope: :pipeline
|
|
# # Or
|
|
# partitionable scope: ->(record) { record.partition_value }
|
|
#
|
|
#
|
|
module Partitionable
|
|
extend ActiveSupport::Concern
|
|
include ::Gitlab::Utils::StrongMemoize
|
|
|
|
module Testing
|
|
InclusionError = Class.new(StandardError)
|
|
|
|
PARTITIONABLE_MODELS = %w[
|
|
CommitStatus
|
|
Ci::BuildMetadata
|
|
Ci::Stage
|
|
Ci::JobArtifact
|
|
Ci::PipelineVariable
|
|
Ci::Pipeline
|
|
].freeze
|
|
|
|
def self.check_inclusion(klass)
|
|
return if PARTITIONABLE_MODELS.include?(klass.name)
|
|
|
|
raise Partitionable::Testing::InclusionError,
|
|
"#{klass} must be included in PARTITIONABLE_MODELS"
|
|
|
|
rescue InclusionError => e
|
|
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
|
|
end
|
|
end
|
|
|
|
included do
|
|
Partitionable::Testing.check_inclusion(self)
|
|
|
|
before_validation :set_partition_id, on: :create
|
|
validates :partition_id, presence: true
|
|
|
|
def set_partition_id
|
|
return if partition_id_changed? && partition_id.present?
|
|
return unless partition_scope_value
|
|
|
|
self.partition_id = partition_scope_value
|
|
end
|
|
end
|
|
|
|
class_methods do
|
|
private
|
|
|
|
def partitionable(scope:)
|
|
define_method(:partition_scope_value) do
|
|
strong_memoize(:partition_scope_value) do
|
|
next Ci::Pipeline.current_partition_value if respond_to?(:importing?) && importing?
|
|
|
|
record = scope.to_proc.call(self)
|
|
record.respond_to?(:partition_id) ? record.partition_id : record
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|