Class: ActiveRecord::Materialized::Metadata Private
- Inherits:
-
Object
- Object
- ActiveRecord::Materialized::Metadata
- Defined in:
- lib/activerecord/materialized/metadata.rb,
lib/activerecord/materialized/metadata/schema.rb,
lib/activerecord/materialized/metadata/timestamps.rb,
lib/activerecord/materialized/metadata/reconciliation.rb,
lib/activerecord/materialized/metadata/maintenance_payload.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Reads and writes a view's freshness metadata row (dirty, warm, last_refreshed_at, …).
Defined Under Namespace
Modules: MaintenancePayload, Reconciliation, Schema, Timestamps
Instance Attribute Summary collapse
- #view_class ⇒ Object readonly private
Instance Method Summary collapse
-
#bump_fresh_set_generation! ⇒ Object
private
Advance the fresh-set epoch atomically so every mark stamped with an earlier value is treated as stale — used by PartitionState#reset! to invalidate a cold view's whole fresh set on a widen.
- #clear_maintenance_payload! ⇒ Object private
- #dirty? ⇒ Boolean private
- #ensure_schema! ⇒ Object private
-
#fresh_set_generation ⇒ Object
private
The current fresh-set epoch for this view (see PartitionState).
-
#initialize(view_class) ⇒ Metadata
constructor
private
A new instance of Metadata.
- #last_refreshed_at ⇒ Object private
- #maintenance_payload ⇒ Object private
- #mark_dirty! ⇒ Object private
- #mark_failed!(error) ⇒ Object private
- #mark_refreshed!(row_count:, duration_ms:) ⇒ Object private
- #mark_refreshing! ⇒ Object private
- #mark_warm! ⇒ Object private
-
#record ⇒ Object
private
Single entry point for the metadata row.
- #record_maintenance_payload!(payload) ⇒ Object private
- #refresh_duration_ms ⇒ Object private
- #refreshing? ⇒ Boolean private
- #row_count ⇒ Object private
- #stale?(max_staleness: view_class.resolved_max_staleness) ⇒ Boolean private
-
#warm? ⇒ Boolean
private
Warm once fully materialized via rebuild!; cold views read through.
Constructor Details
#initialize(view_class) ⇒ Metadata
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Metadata.
16 17 18 19 |
# File 'lib/activerecord/materialized/metadata.rb', line 16 def initialize(view_class) @view_class = view_class @schema_ensured = false end |
Instance Attribute Details
#view_class ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
14 15 16 |
# File 'lib/activerecord/materialized/metadata.rb', line 14 def view_class @view_class end |
Instance Method Details
#bump_fresh_set_generation! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Advance the fresh-set epoch atomically so every mark stamped with an earlier value is treated as stale — used by PartitionState#reset! to invalidate a cold view's whole fresh set on a widen. Ensures the row exists first (create_or_find_by absorbs a concurrent first insert), then a single atomic SQL increment (never a read-then-write), so two concurrent resets can't lost-update the epoch — a populate that captured any earlier value still fails all_fresh?. Portable across adapters.
76 77 78 79 80 81 82 83 84 85 |
# File 'lib/activerecord/materialized/metadata.rb', line 76 def bump_fresh_set_generation! ensure_schema! MetadataRecord.create_or_find_by(view_name: view_class.view_key) connection = view_class.connection table = connection.quote_table_name(::ActiveRecord::Materialized.) connection.execute( "UPDATE #{table} SET fresh_set_generation = fresh_set_generation + 1 " \ "WHERE view_name = #{connection.quote(view_class.view_key)}" ) end |
#clear_maintenance_payload! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
112 113 114 |
# File 'lib/activerecord/materialized/metadata.rb', line 112 def clear_maintenance_payload! MaintenancePayload.clear!(self) end |
#dirty? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
52 53 54 |
# File 'lib/activerecord/materialized/metadata.rb', line 52 def dirty? !!record.dirty? end |
#ensure_schema! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
29 30 31 32 33 34 |
# File 'lib/activerecord/materialized/metadata.rb', line 29 def ensure_schema! return if @schema_ensured Schema.ensure_table!(view_class) @schema_ensured = true end |
#fresh_set_generation ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The current fresh-set epoch for this view (see PartitionState). A populate captures it before its source read; all_fresh? honours only marks stamped with the current value. (#120)
67 68 69 |
# File 'lib/activerecord/materialized/metadata.rb', line 67 def fresh_set_generation record.fresh_set_generation end |
#last_refreshed_at ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
36 37 38 |
# File 'lib/activerecord/materialized/metadata.rb', line 36 def last_refreshed_at record.last_refreshed_at end |
#maintenance_payload ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
108 109 110 |
# File 'lib/activerecord/materialized/metadata.rb', line 108 def maintenance_payload MaintenancePayload.fetch(self) end |
#mark_dirty! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
100 101 102 |
# File 'lib/activerecord/materialized/metadata.rb', line 100 def mark_dirty! record.update!(dirty: true) end |
#mark_failed!(error) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
135 136 137 138 139 140 |
# File 'lib/activerecord/materialized/metadata.rb', line 135 def mark_failed!(error) record.update!( refreshing: false, last_error: error. ) end |
#mark_refreshed!(row_count:, duration_ms:) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/activerecord/materialized/metadata.rb', line 123 def mark_refreshed!(row_count:, duration_ms:) record.update!( last_refreshed_at: Timestamps.current, refreshing: false, dirty: false, row_count: row_count, refresh_duration_ms: duration_ms, last_error: nil, maintenance_payload: nil ) end |
#mark_refreshing! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
116 117 118 119 120 121 |
# File 'lib/activerecord/materialized/metadata.rb', line 116 def mark_refreshing! record.update!( refreshing: true, last_error: nil ) end |
#mark_warm! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
61 62 63 |
# File 'lib/activerecord/materialized/metadata.rb', line 61 def mark_warm! record.update!(warm: true) end |
#record ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Single entry point for the metadata row. Provision the schema once per instance — re-ensuring on every access thrashes the schema cache and makes high-write workloads quadratic.
24 25 26 27 |
# File 'lib/activerecord/materialized/metadata.rb', line 24 def record ensure_schema! MetadataRecord.find_or_initialize_by(view_name: view_class.view_key) end |
#record_maintenance_payload!(payload) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
104 105 106 |
# File 'lib/activerecord/materialized/metadata.rb', line 104 def record_maintenance_payload!(payload) MaintenancePayload.record!(self, payload) end |
#refresh_duration_ms ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
48 49 50 |
# File 'lib/activerecord/materialized/metadata.rb', line 48 def refresh_duration_ms record.refresh_duration_ms end |
#refreshing? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
40 41 42 |
# File 'lib/activerecord/materialized/metadata.rb', line 40 def refreshing? !!record.refreshing? end |
#row_count ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
44 45 46 |
# File 'lib/activerecord/materialized/metadata.rb', line 44 def row_count record.row_count end |
#stale?(max_staleness: view_class.resolved_max_staleness) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/activerecord/materialized/metadata.rb', line 87 def stale?(max_staleness: view_class.resolved_max_staleness) return true if dirty? return true if last_refreshed_at.nil? return false if max_staleness.nil? # A reconcile verifies contents against the source, so it resets the staleness clock like a # refresh — measure age from whichever happened later. The replica-lag budget tightens the # window: a replica read trails the primary by the lag, so the view goes stale that much # sooner to keep replica reads within max_staleness. freshest = [last_refreshed_at, record.last_reconciled_at].compact.max_by(&:to_time) freshest.to_time < Timestamps.threshold(effective_staleness(max_staleness)).to_time end |
#warm? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Warm once fully materialized via rebuild!; cold views read through.
57 58 59 |
# File 'lib/activerecord/materialized/metadata.rb', line 57 def warm? !!record.warm? end |