Class: Upkeep::Subscriptions::ActiveRecordStore
- Inherits:
-
BaseStore
- Object
- BaseStore
- Upkeep::Subscriptions::ActiveRecordStore
show all
- Defined in:
- lib/upkeep/subscriptions/active_record_store.rb
Defined Under Namespace
Classes: DeferredIndexWrite, IndexEntryRecord, ShapeIndexEntryRecord, SubscriptionRecord
Constant Summary
collapse
- LOOKUP_NOTIFICATION =
LayeredReverseIndex::LOOKUP_NOTIFICATION
- REGISTER_NOTIFICATION =
"register_subscription_store.upkeep"
- ACTIVATE_NOTIFICATION =
"activate_subscription_store.upkeep"
- PERSIST_NOTIFICATION =
ActiveRecordSubscriptionPersistence::PERSIST_NOTIFICATION
- DURABILITY_MODE =
"sync_subscription_row_index_on_subscribe"
- INDEX_DURABILITY =
"on_subscribe"
- REQUIRED_SCHEMA =
{
"upkeep_subscriptions" => {
"id" => :string,
"subscriber_id" => :string,
"recorder_snapshot" => :json,
"metadata" => :json,
"subscription_shape_key" => :string,
"created_at" => :datetime,
"updated_at" => :datetime
},
"upkeep_subscription_index_entries" => {
"subscription_id" => :string,
"lookup_key_digest" => :string,
"dependency_source" => :string,
"lookup_table" => :string,
"lookup_record_id_snapshot" => :json,
"lookup_attribute" => :string,
"dependency_table" => :string,
"dependency_predicate_digest" => :string,
"dependency_metadata_snapshot" => :json,
"owner_ids_snapshot" => :json,
"created_at" => :datetime,
"updated_at" => :datetime
},
"upkeep_subscription_shape_index_entries" => {
"subscription_shape_key" => :string,
"lookup_key_digest" => :string,
"dependency_source" => :string,
"lookup_table" => :string,
"lookup_record_id_snapshot" => :json,
"lookup_attribute" => :string,
"dependency_table" => :string,
"dependency_predicate_digest" => :string,
"dependency_metadata_snapshot" => :json,
"owner_ids_snapshot" => :json,
"created_at" => :datetime,
"updated_at" => :datetime
}
}.freeze
Constants inherited
from BaseStore
BaseStore::DEFAULT_SUBSCRIPTION_TTL, BaseStore::PRUNE_NOTIFICATION, BaseStore::TRIM_BATCH_LIMIT, BaseStore::TRIM_EVERY
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Methods inherited from BaseStore
#explain, #fetch, #touch, #unregister
Constructor Details
#initialize(subscription_record: SubscriptionRecord, index_record: IndexEntryRecord, shape_index_record: ShapeIndexEntryRecord) ⇒ ActiveRecordStore
Returns a new instance of ActiveRecordStore.
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 90
def initialize(subscription_record: SubscriptionRecord, index_record: IndexEntryRecord, shape_index_record: ShapeIndexEntryRecord)
@subscription_record = subscription_record
@index_record = index_record
@shape_index_record = shape_index_record
@index_builder = ReverseIndex.new
@pending_registry = ActiveRegistry.new
@active_registry = ActiveRegistry.new
@deferred_index_writes = {}
@deferred_index_mutex = Mutex.new
@persistence = ActiveRecordSubscriptionPersistence.new(
subscription_record: subscription_record,
index_record: index_record,
shape_index_record: shape_index_record,
index_builder: index_builder
)
persistent_index = PersistentReverseIndex.new(
reverse_index: index_builder,
index_record: index_record,
shape_index_record: shape_index_record,
subscription_record: subscription_record
)
@reverse_index = LayeredReverseIndex.new(
active_index: active_registry,
persistent_index: persistent_index,
persistent_count: -> { persistence.count },
store: "active_record",
pending_index: pending_registry
)
end
|
Instance Attribute Details
#reverse_index ⇒ Object
Returns the value of attribute reverse_index.
86
87
88
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 86
def reverse_index
@reverse_index
end
|
Class Method Details
.available?(connect: false) ⇒ Boolean
120
121
122
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 120
def self.available?(connect: false)
schema_errors(connect: connect).empty?
end
|
.schema_errors(connect: false) ⇒ Object
124
125
126
127
128
129
130
131
132
133
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 124
def self.schema_errors(connect: false)
return ["Active Record is not connected"] unless ActiveRecord::Base.connected? || connect
connection = ActiveRecord::Base.connection
REQUIRED_SCHEMA.flat_map { |table, columns| schema_errors_for_table(connection, table, columns) }
rescue ActiveRecord::ConnectionNotEstablished, ActiveRecord::NoDatabaseError => error
[error.message]
rescue ActiveRecord::StatementInvalid => error
["database schema could not be inspected: #{error.message}"]
end
|
Instance Method Details
#activate(id) ⇒ Object
183
184
185
186
187
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 183
def activate(id)
with_optional_notification(ACTIVATE_NOTIFICATION, { store: "active_record", subscription_id: id }) do |payload|
activate_subscription(id, payload: payload)
end
end
|
#prune_stale!(older_than: stale_threshold, limit: nil) ⇒ Object
189
190
191
192
193
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 189
def prune_stale!(older_than: stale_threshold, limit: nil)
stale_ids = persistence.prune_stale!(older_than: older_than, limit: limit)
active_registry.unregister(stale_ids)
stale_ids.size
end
|
#register(subscriber_id:, recorder:, metadata: {}, entries: nil) ⇒ Object
171
172
173
174
175
176
177
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 171
def register(subscriber_id:, recorder:, metadata: {}, entries: nil)
subscription = with_optional_notification(REGISTER_NOTIFICATION, { store: "active_record" }) do |payload|
register_subscription(subscriber_id, recorder, metadata, entries: entries, payload: payload)
end
trim_opportunistically
subscription
end
|
#reset ⇒ Object
210
211
212
213
214
215
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 210
def reset
clear_deferred_index_writes
pending_registry.reset
active_registry.reset
persistence.reset
end
|
#shutdown ⇒ Object
179
180
181
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 179
def shutdown
clear_deferred_index_writes
end
|
#subscriptions ⇒ Object
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 195
def subscriptions
persistent_count = persistence.count
in_memory_subscriptions = (active_registry.subscriptions + pending_registry.subscriptions).to_h do |subscription|
[subscription.id, subscription]
end
return in_memory_subscriptions.values if in_memory_subscriptions.size >= persistent_count
seen_ids = {}
persisted = persistence.subscriptions.map do |subscription|
seen_ids[subscription.id] = true
in_memory_subscriptions.fetch(subscription.id, subscription)
end
persisted + in_memory_subscriptions.values.reject { |subscription| seen_ids[subscription.id] }
end
|
#summary ⇒ Object
217
218
219
220
221
222
223
224
225
226
227
228
229
|
# File 'lib/upkeep/subscriptions/active_record_store.rb', line 217
def summary
persistent_count = persistence.count
pending_count = pending_registry.count
active_count = active_registry.count
{
subscriptions: [persistent_count, active_count + pending_count].max,
persistent_subscriptions: persistent_count,
pending_subscriptions: pending_count,
active_subscriptions: active_count,
deferred_index_subscriptions: deferred_index_count,
reverse_index: reverse_index.summary
}
end
|