Module: MaquinaStream::Streamable

Extended by:
ActiveSupport::Concern
Defined in:
lib/maquina_stream/streamable.rb

Overview

Host contract for a streamable record. The host owns persistence; the engine never guesses a broadcast target and never invents authorization.

class Message < ApplicationRecord
  include MaquinaStream::Streamable

  maquina_stream buffer: :content,
                 stream_for: ->(m) { [m.conversation, :messages] }
end

The macro generates the contract methods when the column names match (see docs/streaming.md). Anything the host defines itself wins, and a method whose backing column is missing raises ContractError naming the method, the column and the class.

What the columns must be

Method Column it reads
#maquina_stream_buffer, #maquina_stream_append whatever buffer: named
#maquina_stream_sequence, #maquina_stream_advance stream_sequence, an integer
#maquina_stream_open?, #maquina_stream_seal!, #maquina_stream_status stream_status, a string holding open / complete / cancelled / errored / timed_out

#maquina_stream_id needs no column — it is to_param. #maquina_stream_target needs none either; it calls the stream_for: lambda.

The generated methods

Method Returns
#maquina_stream_id String, stable and unique per message
#maquina_stream_buffer String, the raw markdown written so far
#maquina_stream_append(text) the whole buffer after appending and persisting
#maquina_stream_sequence Integer, monotonic, one per frame that went out
#maquina_stream_advance Integer, the next sequence number, incremented atomically
#maquina_stream_open? Boolean
#maquina_stream_status the recorded end state as a Symbol, or nil while open
#maquina_stream_seal!(status: :complete) the status Symbol it sealed with
#maquina_stream_target the Turbo broadcast target, from stream_for:

Each is documented on Streamable::Generated. Defining any of them in the model body overrides the generated one — the macro includes a module, so the class body always wins.

Defined Under Namespace

Modules: Generated

Constant Summary collapse

SEQUENCE_COLUMN =

The column #maquina_stream_sequence and #maquina_stream_advance read.

:stream_sequence
STATUS_COLUMN =

The column #maquina_stream_open?, #maquina_stream_status and #maquina_stream_seal! read.

:stream_status
OPEN_STATUS =

The one value of STATUS_COLUMN that means the stream is still being written. Everything else is a seal.

"open"
SEAL_STATUSES =

A stream that timed out is not the same as one that errored: nothing went wrong, the model simply stopped answering, and the partial text it did produce is still worth keeping and replaying.

i[complete cancelled errored timed_out].freeze
CONTRACT_METHODS =

Every method a host must answer to. The macro generates all of them; a host that cannot use the macro implements this list itself.

i[
  maquina_stream_id
  maquina_stream_buffer
  maquina_stream_append
  maquina_stream_sequence
  maquina_stream_advance
  maquina_stream_open?
  maquina_stream_seal!
  maquina_stream_target
].freeze