Module: ActiveRecord::Materialized::ViewIncrementalClassMethods::ClassMethods

Included in:
ActiveRecord::Materialized::ViewConfigurationClassMethods::ClassMethods
Defined in:
lib/activerecord/materialized/view_incremental_class_methods.rb

Overview

The incremental-maintenance DSL methods available on a ActiveRecord::Materialized::View subclass.

Instance Method Summary collapse

Instance Method Details

#aggregate_analysisObject



95
96
97
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 95

def aggregate_analysis
  AggregateAnalysis.new(view_class.resolved_source)
end

#delta_maintaining?Boolean

A warm view with all-distributive aggregates uses summary-delta IVM; otherwise writes drive scoped recompute. Restricted to callback-backed views: their in-app writes arrive exactly once, so applying signed deltas is safe. Externally fed views recompute their partitions instead, so at-least-once or duplicate delivery converges rather than double-counting.

Returns:

  • (Boolean)


104
105
106
107
108
109
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 104

def delta_maintaining?
  resolved_refresh_mode != :full &&
    view_class.resolved_change_source == ChangeSource::CALLBACKS &&
    view_class.materialized? &&
    aggregate_analysis.delta_maintainable?
end

#incremental_from(&block) ⇒ void

This method returns an undefined value.

Overrides the source relation used for incremental maintenance (defaults to materialized_from).

Yield Returns:

  • (ActiveRecord::Relation)

    the relation to maintain incrementally



38
39
40
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 38

def incremental_from(&block)
  @incremental_source_definition = block
end

#incremental_key_columnsObject



119
120
121
122
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 119

def incremental_key_columns
  columns = instance_variable_get(:@incremental_key_columns)
  columns.nil? ? [] : columns
end

#incremental_keys(*columns) ⇒ void

This method returns an undefined value.

Declares the explicit GROUP BY key columns used to scope incremental maintenance.

Parameters:

  • columns (Array<Symbol>)

    the key columns identifying a partition



46
47
48
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 46

def incremental_keys(*columns)
  @incremental_key_columns = columns.map(&:to_s)
end

#incremental_source_override?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 111

def incremental_source_override?
  !@incremental_source_definition.nil?
end

#incrementally_maintainable?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 91

def incrementally_maintainable?
  resolved_refresh_mode != :full && view_definition.incrementally_maintainable?
end

#maintenance_key_columnsObject



85
86
87
88
89
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 85

def maintenance_key_columns
  return incremental_key_columns if incremental_key_columns.any?

  view_definition.group_key_columns
end

#partition_key_for(table) {|change| ... } ⇒ void

This method returns an undefined value.

Maps a write on table to the partition key(s) it affects — for a view whose GROUP BY key lives on a joined/parent table, so the written row's own payload can't supply it. The block receives the WriteChange and returns the key value(s): a scalar (or array of scalars) for a single-column key, a tuple (or array of tuples) for a composite key; returning nothing falls back to a full recompute. Trades a small lookup per write for avoiding one.

Parameters:

  • table (Symbol, String)

    the dependency table the resolver applies to

Yield Parameters:

  • change (WriteChange)

    the committed write on table

Yield Returns:

  • (Object, Array, nil)

    the affected partition key(s), or nil to force a full recompute



61
62
63
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 61

def partition_key_for(table, &block)
  partition_key_resolvers[table.to_s] = block
end

#partition_key_resolver_for(table_name) ⇒ Object



65
66
67
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 65

def partition_key_resolver_for(table_name)
  partition_key_resolvers[table_name]
end

#partition_key_resolversObject



69
70
71
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 69

def partition_key_resolvers
  @partition_key_resolvers ||= {}
end

#record_write_change!(change) ⇒ Object



115
116
117
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 115

def record_write_change!(change)
  WriteMaintenance.new(view_class).record!(change)
end

#refresh_mode(mode) ⇒ void

This method returns an undefined value.

Sets whether maintenance is incremental (default) or a full recompute on every change.

Parameters:

  • mode (Symbol)

    :incremental (default) or :full



25
26
27
28
29
30
31
32
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 25

def refresh_mode(mode)
  mode = mode.to_sym
  unless REFRESH_MODES.include?(mode)
    raise ArgumentError, "unknown refresh mode #{mode.inspect}; expected one of #{REFRESH_MODES.inspect}"
  end

  instance_variable_set(:@refresh_mode, mode)
end

#resolved_incremental_sourceObject



124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 124

def resolved_incremental_source
  unless incremental_source_override?
    Kernel.raise ArgumentError,
                 "incremental_from override is not configured for #{view_class.name || view_class.view_key}"
  end

  view_class.send(
    :resolve_source_definition,
    @incremental_source_definition,
    "incremental_from is required for #{view_class.name || view_class.view_key}"
  )
end

#resolved_refresh_modeObject



73
74
75
76
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 73

def resolved_refresh_mode
  mode = instance_variable_get(:@refresh_mode)
  mode || :incremental
end

#view_classObject



17
18
19
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 17

def view_class
  self
end

#view_definitionObject



78
79
80
81
82
83
# File 'lib/activerecord/materialized/view_incremental_class_methods.rb', line 78

def view_definition
  ViewDefinition.new(
    view_class.resolved_source,
    explicit_group_keys: incremental_key_columns.presence
  )
end