Class: ActiveRecord::Materialized::PartitionState
- Inherits:
-
Object
- Object
- ActiveRecord::Materialized::PartitionState
- Extended by:
- T::Sig
- Defined in:
- lib/activerecord/materialized/partition_state.rb
Overview
Tracks which partitions of a cold view have been materialized (“fresh”) so a read can decide whether a partition is served from the cache or read through to the source. Warm views are fully materialized and ignore this.
Constant Summary collapse
- KeyTuple =
T.type_alias { T::Array[T.untyped] }
Class Method Summary collapse
- .cartesian(value_lists) ⇒ Object
- .key_value_lists(conditions, group_keys) ⇒ Object
- .keys_from(view_class, args) ⇒ Object
- .single_hash(args) ⇒ Object
Instance Method Summary collapse
- #all_fresh?(key_tuples) ⇒ Boolean
-
#initialize(view_class) ⇒ PartitionState
constructor
A new instance of PartitionState.
- #mark_fresh!(key_tuples) ⇒ Object
- #mark_stale!(key_tuples) ⇒ Object
- #reset! ⇒ Object
Constructor Details
#initialize(view_class) ⇒ PartitionState
Returns a new instance of PartitionState.
15 16 17 |
# File 'lib/activerecord/materialized/partition_state.rb', line 15 def initialize(view_class) @view_class = view_class end |
Class Method Details
.cartesian(value_lists) ⇒ Object
86 87 88 89 90 91 92 |
# File 'lib/activerecord/materialized/partition_state.rb', line 86 def self.cartesian(value_lists) return nil if value_lists.any?(&:empty?) value_lists.reduce([[]]) do |tuples, values| tuples.flat_map { |tuple| values.map { |value| tuple + [value] } } end end |
.key_value_lists(conditions, group_keys) ⇒ Object
78 79 80 81 82 83 |
# File 'lib/activerecord/materialized/partition_state.rb', line 78 def self.key_value_lists(conditions, group_keys) normalized = conditions.transform_keys(&:to_s) return nil unless normalized.keys.sort == group_keys.sort group_keys.map { |column| Array(normalized.fetch(column)).map(&:to_s) } end |
.keys_from(view_class, args) ⇒ Object
55 56 57 58 59 60 61 62 63 64 |
# File 'lib/activerecord/materialized/partition_state.rb', line 55 def self.keys_from(view_class, args) conditions = single_hash(args) return nil if conditions.nil? group_keys = view_class.maintenance_key_columns return nil if group_keys.empty? value_lists = key_value_lists(conditions, group_keys) value_lists.nil? ? nil : cartesian(value_lists) end |
.single_hash(args) ⇒ Object
67 68 69 70 71 72 |
# File 'lib/activerecord/materialized/partition_state.rb', line 67 def self.single_hash(args) return nil unless args.length == 1 conditions = args.fetch(0) conditions.is_a?(Hash) ? conditions : nil end |
Instance Method Details
#all_fresh?(key_tuples) ⇒ Boolean
20 21 22 23 24 25 26 |
# File 'lib/activerecord/materialized/partition_state.rb', line 20 def all_fresh?(key_tuples) return false if key_tuples.empty? ensure_table! serialized = key_tuples.map { |tuple| serialize(tuple) }.uniq scope.where(partition_key: serialized).count == serialized.size end |
#mark_fresh!(key_tuples) ⇒ Object
29 30 31 32 33 34 35 36 |
# File 'lib/activerecord/materialized/partition_state.rb', line 29 def mark_fresh!(key_tuples) return if key_tuples.empty? ensure_table! key_tuples.uniq.each do |tuple| PartitionRecord.create_or_find_by(view_name: view_key, partition_key: serialize(tuple)) end end |
#mark_stale!(key_tuples) ⇒ Object
39 40 41 42 43 44 |
# File 'lib/activerecord/materialized/partition_state.rb', line 39 def mark_stale!(key_tuples) return if key_tuples.empty? ensure_table! scope.where(partition_key: key_tuples.map { |tuple| serialize(tuple) }).delete_all end |
#reset! ⇒ Object
47 48 49 50 |
# File 'lib/activerecord/materialized/partition_state.rb', line 47 def reset! ensure_table! scope.delete_all end |