Class: Gitlab::Database::Partitioning::SlidingListStrategy
- Inherits:
-
BaseStrategy
- Object
- BaseStrategy
- Gitlab::Database::Partitioning::SlidingListStrategy
- Defined in:
- lib/gitlab/database/partitioning/sliding_list_strategy.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#analyze_interval ⇒ Object
readonly
Returns the value of attribute analyze_interval.
-
#detach_partition_if ⇒ Object
readonly
Returns the value of attribute detach_partition_if.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
-
#next_partition_if ⇒ Object
readonly
Returns the value of attribute next_partition_if.
-
#partitioning_key ⇒ Object
readonly
Returns the value of attribute partitioning_key.
Instance Method Summary collapse
- #active_partition ⇒ Object
-
#after_adding_partitions ⇒ Object
The partition manager is initialized with both connections and creates partitions in both databases, but here we change the default on the model’s connection, meaning that it will not respect the manager’s connection config so we need to check that it’s changing the default only when called with the model’s connection.
- #current_partitions ⇒ Object
- #extra_partitions ⇒ Object
- #initial_partition ⇒ Object
-
#initialize(model, partitioning_key, next_partition_if:, detach_partition_if:, analyze_interval: nil) ⇒ SlidingListStrategy
constructor
A new instance of SlidingListStrategy.
- #missing_partitions ⇒ Object
- #next_partition ⇒ Object
- #no_partitions_exist? ⇒ Boolean
- #validate_and_fix ⇒ Object
Constructor Details
#initialize(model, partitioning_key, next_partition_if:, detach_partition_if:, analyze_interval: nil) ⇒ SlidingListStrategy
Returns a new instance of SlidingListStrategy.
11 12 13 14 15 16 17 18 19 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 11 def initialize(model, partitioning_key, next_partition_if:, detach_partition_if:, analyze_interval: nil) @model = model @partitioning_key = partitioning_key @next_partition_if = next_partition_if @detach_partition_if = detach_partition_if @analyze_interval = analyze_interval ensure_partitioning_column_ignored_or_readonly! end |
Instance Attribute Details
#analyze_interval ⇒ Object (readonly)
Returns the value of attribute analyze_interval.
7 8 9 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 7 def analyze_interval @analyze_interval end |
#detach_partition_if ⇒ Object (readonly)
Returns the value of attribute detach_partition_if.
7 8 9 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 7 def detach_partition_if @detach_partition_if end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
7 8 9 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 7 def model @model end |
#next_partition_if ⇒ Object (readonly)
Returns the value of attribute next_partition_if.
7 8 9 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 7 def next_partition_if @next_partition_if end |
#partitioning_key ⇒ Object (readonly)
Returns the value of attribute partitioning_key.
7 8 9 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 7 def partitioning_key @partitioning_key end |
Instance Method Details
#active_partition ⇒ Object
101 102 103 104 105 106 107 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 101 def active_partition ensure_connection_set # The current partitions list is sorted, so the last partition has the highest value # This is the only partition that receives inserts. current_partitions.last end |
#after_adding_partitions ⇒ Object
The partition manager is initialized with both connections and creates partitions in both databases, but here we change the default on the model’s connection, meaning that it will not respect the manager’s connection config so we need to check that it’s changing the default only when called with the model’s connection. Also since we prevent writes in the other database, we should not change the default there.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 82 def after_adding_partitions ensure_connection_set if different_connection_names? Gitlab::AppLogger.warn( message: 'Skipping changing column default because connections mismatch', event: :partition_manager_after_adding_partitions_connection_mismatch, model_connection_name: Gitlab::Database.db_config_name(model.connection), shared_connection_name: Gitlab::Database.db_config_name(Gitlab::Database::SharedModel.connection), table_name: model.table_name ) return end active_value = active_partition.value model.connection.change_column_default(model.table_name, partitioning_key, active_value) end |
#current_partitions ⇒ Object
21 22 23 24 25 26 27 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 21 def current_partitions ensure_connection_set Gitlab::Database::PostgresPartition.for_parent_table(table_name).map do |partition| SingleNumericListPartition.from_sql(table_name, partition.name, partition.condition) end.sort end |
#extra_partitions ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 53 def extra_partitions ensure_connection_set possibly_extra = current_partitions[0...-1] # Never consider the most recent partition extra = possibly_extra.take_while { |p| detach_partition_if.call(p) } default_value = current_default_value if extra.any? { |p| p.value == default_value } Gitlab::AppLogger.error( message: "Inconsistent partition detected: partition with value #{current_default_value} should " \ "not be deleted because it's used as the default value.", partition_number: current_default_value, table_name: model.table_name ) extra = extra.reject { |p| p.value == default_value } end extra end |
#initial_partition ⇒ Object
41 42 43 44 45 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 41 def initial_partition ensure_connection_set SingleNumericListPartition.new(table_name, 1) end |
#missing_partitions ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 29 def missing_partitions ensure_connection_set if no_partitions_exist? [initial_partition] elsif next_partition_if.call(active_partition) [next_partition] else [] end end |
#next_partition ⇒ Object
47 48 49 50 51 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 47 def next_partition ensure_connection_set SingleNumericListPartition.new(table_name, active_partition.value + 1) end |
#no_partitions_exist? ⇒ Boolean
109 110 111 112 113 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 109 def no_partitions_exist? ensure_connection_set current_partitions.empty? end |
#validate_and_fix ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/gitlab/database/partitioning/sliding_list_strategy.rb', line 115 def validate_and_fix ensure_connection_set if different_connection_names? Gitlab::AppLogger.warn( message: 'Skipping fixing column default because connections mismatch', event: :partition_manager_validate_and_fix_connection_mismatch, model_connection_name: Gitlab::Database.db_config_name(model.connection), shared_connection_name: Gitlab::Database.db_config_name(Gitlab::Database::SharedModel.connection), table_name: model.table_name ) return end return if no_partitions_exist? old_default_value = current_default_value expected_default_value = active_partition.value if old_default_value != expected_default_value with_lock_retries do model.connection.execute("LOCK TABLE #{model.table_name} IN ACCESS EXCLUSIVE MODE") old_default_value = current_default_value expected_default_value = active_partition.value if old_default_value == expected_default_value Gitlab::AppLogger.warn( message: "Table partitions or partition key default value have been changed by another process", table_name: table_name, default_value: expected_default_value ) raise ActiveRecord::Rollback end model.connection.change_column_default(model.table_name, partitioning_key, expected_default_value) Gitlab::AppLogger.warn( message: "Fixed default value of sliding_list_strategy partitioning_key", column: partitioning_key, table_name: table_name, connection_name: model.connection.pool.db_config.name, old_value: old_default_value, new_value: expected_default_value ) end end end |