Class: Mistri::Stores::ActiveRecord

Inherits:
Object
  • Object
show all
Defined in:
lib/mistri/stores/active_record.rb

Overview

Entries in the host's own database, through a model class the host supplies, so sessions live where application data lives: MySQL, Postgres, whatever the app runs. Not auto-required; load it with require "mistri/stores/active_record".

The model needs three columns: session_id (string, indexed), position (integer), payload (text). A migration to copy:

create_table :mistri_entries do |t|
t.string :session_id, null: false, index: true
t.integer :position, null: false
t.text :payload, size: :medium, null: false
t.timestamps
end
add_index :mistri_entries, [:session_id, :position], unique: true

The unique index is load-bearing: one session has one writer at a time (the loop is serial), and if a host ever runs two agents on one session, a colliding append raises instead of silently corrupting entry order.

Reads select only (position, payload) and sort in Ruby: ORDER BY over rows carrying multi-megabyte payloads exhausts MySQL's sort buffer.

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ ActiveRecord

Returns a new instance of ActiveRecord.



30
31
32
# File 'lib/mistri/stores/active_record.rb', line 30

def initialize(model)
  @model = model
end

Instance Method Details

#append(id, entry) ⇒ Object



34
35
36
37
38
# File 'lib/mistri/stores/active_record.rb', line 34

def append(id, entry)
  position = @model.where(session_id: id).maximum(:position).to_i + 1
  @model.create!(session_id: id, position: position, payload: JSON.generate(entry))
  nil
end

#load(id) ⇒ Object



40
41
42
43
44
# File 'lib/mistri/stores/active_record.rb', line 40

def load(id)
  @model.where(session_id: id).pluck(:position, :payload)
        .sort_by(&:first)
        .map { |_position, payload| JSON.parse(payload) }
end