Class: Phronomy::StateStore::ActiveRecord
- Defined in:
- lib/phronomy/state_store/active_record.rb
Overview
ActiveRecord-backed state store. Persists graph state to a relational database using an AR model.
The model_class must respond to: .find_by(thread_id:) .find_or_initialize_by(thread_id:) #state_json=, #save! .where(thread_id:).delete_all
Minimal migration: create_table :phronomy_states do |t| t.string :thread_id, null: false, index: { unique: true } t.text :state_json, null: false t.timestamps end
Instance Method Summary collapse
-
#clear(thread_id) ⇒ self
Deletes the state for the given thread_id.
-
#initialize(model_class:, encryptor: nil) ⇒ ActiveRecord
constructor
A new instance of ActiveRecord.
-
#load(thread_id) ⇒ Object?
Loads and deserializes the state for the given thread_id.
-
#save(state) ⇒ self
Serializes and upserts the state for the given thread_id.
Constructor Details
#initialize(model_class:, encryptor: nil) ⇒ ActiveRecord
Returns a new instance of ActiveRecord.
35 36 37 38 |
# File 'lib/phronomy/state_store/active_record.rb', line 35 def initialize(model_class:, encryptor: nil) @model_class = model_class @encryptor = encryptor end |
Instance Method Details
#clear(thread_id) ⇒ self
Deletes the state for the given thread_id.
70 71 72 73 |
# File 'lib/phronomy/state_store/active_record.rb', line 70 def clear(thread_id) @model_class.where(thread_id: thread_id).delete_all self end |
#load(thread_id) ⇒ Object?
Loads and deserializes the state for the given thread_id.
59 60 61 62 63 64 65 66 |
# File 'lib/phronomy/state_store/active_record.rb', line 59 def load(thread_id) record = @model_class.find_by(thread_id: thread_id) return nil unless record payload = record.state_json json = @encryptor ? @encryptor.decrypt(payload) : payload deserialize_state(json) end |
#save(state) ⇒ self
Serializes and upserts the state for the given thread_id.
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/phronomy/state_store/active_record.rb', line 43 def save(state) json = serialize_state(state) payload = @encryptor ? @encryptor.encrypt(json) : json # Use upsert to avoid a race condition where two concurrent saves for the # same thread_id would both see "no record" and collide on the unique index. @model_class.upsert( {thread_id: state.thread_id, state_json: payload}, unique_by: :thread_id, update_only: [:state_json] ) self end |