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

switch.rb « partitionable « ci « concerns « models « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6195f92114ff5979052bebd29bd9610946402d3f (plain)
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
# frozen_string_literal: true

module Ci
  module Partitionable
    MUTEX = Mutex.new

    module Switch
      extend ActiveSupport::Concern

      # These methods are cached at the class level and depend on the value
      # of `table_name`, changing that value resets them.
      # `cached_find_by_statement` is used to cache SQL statements which can
      # include the table name.
      #
      SWAPABLE_METHODS = %i[table_name quoted_table_name arel_table
                            predicate_builder cached_find_by_statement].freeze

      included do |base|
        install_partitioned_class(base)
      end

      class_methods do
        # `Class.new(partitionable_model)` triggers `partitionable_model.inherited`
        # and we need the mutex to break the recursion without adding extra accessors
        # on the model. This will be used during code loading, not runtime.
        #
        def install_partitioned_class(partitionable_model)
          Partitionable::MUTEX.synchronize do
            partitioned = Class.new(partitionable_model) do
              self.table_name = partitionable_model.routing_table_name

              def self.routing_class?
                true
              end

              def self.sti_name
                superclass.sti_name
              end
            end

            partitionable_model.const_set(:Partitioned, partitioned)
          end
        end

        def inherited(child_class)
          super
          return if Partitionable::MUTEX.owned?

          install_partitioned_class(child_class)
        end

        def routing_class?
          false
        end

        def routing_table_enabled?
          return false if routing_class?

          Gitlab::SafeRequestStore.fetch(routing_table_name_flag) do
            ::Feature.enabled?(routing_table_name_flag)
          end
        end

        # We're delegating them to the `Partitioned` model.
        # They do not require any check override since they come from AR core
        # (are always defined) and we're using `super` to get the value.
        #
        SWAPABLE_METHODS.each do |name|
          define_method(name) do |*args, &block|
            if routing_table_enabled?
              self::Partitioned.public_send(name, *args, &block) # rubocop: disable GitlabSecurity/PublicSend
            else
              super(*args, &block)
            end
          end
        end

        def type_condition(table = arel_table)
          sti_column = table[inheritance_column]
          sti_names  = ([self] + descendants).map(&:sti_name).uniq

          predicate_builder.build(sti_column, sti_names)
        end
      end
    end
  end
end