Skip to content
Strata is pre-1.0. APIs, protocol, and storage format may change.

strata_client

strata_client — sans-IO client state machine for Strata.

This package is transport-agnostic. It provides:

  • Connection — opaque state holding which documents are joined and whether the server welcome frame has been received.
  • outbound/2 — given a Command, produces the JSON bytes the caller must send over the WebSocket.
  • inbound/2 — feeds a received text frame in; returns the updated Connection and a typed Event (or a StepError if the frame could not be decoded).
  • frames_for_resume/1 — after a reconnect, returns the list of bytes needed to re-join every previously joined document.

The caller wires this state machine to a real WebSocket — browser WebSocket, gun, mist, or any other transport. There is no FFI inside this package, so it compiles unchanged on both the Erlang/BEAM and JavaScript targets.

Things the caller can ask the connection to do.

pub type Command {
Join(document_id: String)
Leave(document_id: String)
SendDelta(document_id: String, state: json.Json)
SendPresence(document_id: String, payload: json.Json)
Create(parent: String, child: String, child_state: json.Json, parent_state: json.Json)
Delete(parent: String, child: String, parent_state: json.Json)
SendPing
}

Subscribe to a document.

Unsubscribe from a document.

SendDelta(document_id: String, state: json.Json)

Section titled “SendDelta(document_id: String, state: json.Json)”

Push a new CRDT state for a document. state is opaque JSON produced by the caller's CRDT layer.

SendPresence(document_id: String, payload: json.Json)

Section titled “SendPresence(document_id: String, payload: json.Json)”

Push a presence update for a document.

Create(parent: String, child: String, child_state: json.Json, parent_state: json.Json)

Section titled “Create(parent: String, child: String, child_state: json.Json, parent_state: json.Json)”

Create child under parent, merging parent_state into the parent document in the same server-side operation. child_state and parent_state are opaque JSON produced by the caller's CRDT layer.

Delete(parent: String, child: String, parent_state: json.Json)

Section titled “Delete(parent: String, child: String, parent_state: json.Json)”

Delete child (and its descendants) from parent, merging parent_state into the parent document in the same server-side operation.

Liveness probe.

Opaque connection state.

pub type Connection

Things the server tells the client about.

pub type Event {
Welcomed(session_id: String, server: String)
Snapshot(document_id: String, state: dynamic.Dynamic)
Deleted(document_id: String)
RemoteDelta(document_id: String, state: dynamic.Dynamic, from: String)
PresenceState(document_id: String, presences: List(presence.Presence))
PresenceDiff(document_id: String, joins: List(presence.Presence), leaves: List(presence.Presence))
ServerError(code: String, message: String)
Pong
}

document_id (and its descendants) was deleted server-side. The document id is removed from joined so a subsequent reconnect does not rejoin it.

Anything that can go wrong while feeding bytes in.

pub type StepError {
ProtocolError(error: error.DecodeError)
}

After a reconnect, returns the bytes needed to re-join every document that was joined before the disconnect. The joined set is preserved in the returned Connection so the caller can keep using the same instance.

pub fn frames_for_resume(Connection) -> #(Connection, List(String))

Feed a received text frame in. Returns the updated connection plus the decoded event, or a StepError if the frame is malformed.

pub fn inbound(
Connection,
String
) -> Result(#(Connection, Event), StepError)

True once the server has sent its welcome frame.

pub fn is_welcomed(Connection) -> Bool

The set of documents this connection has joined (and not yet left).

pub fn joined_documents(Connection) -> List(String)

Build a fresh connection state. Call once per WebSocket session; after a reconnect, call new() again or use the existing instance with frames_for_resume to resubscribe.

pub fn new() -> Connection

Apply a command: returns the updated Connection plus the bytes the caller must send over the WebSocket.

pub fn outbound(
Connection,
Command
) -> #(Connection, String)

The wire protocol version this client speaks.

pub fn protocol_version() -> Int

Server identification string from the welcome frame, or None.

pub fn server_id(Connection) -> option.Option(String)

The server-assigned session id for this connection, or None if the welcome frame has not arrived yet.

pub fn session_id(Connection) -> option.Option(String)