An actor in a room from Elixir: an agent running in your app, a job, a script. It joins like a browser, with the same presence, awareness, locks, transactions and policy, and the people in the room see it.
{:ok, claude} = Issho.join_as(MyApp.Issho, agent, "board:42", on_behalf_of: ada)
{:ok, doc} = Issho.Participant.open(claude, "board:42")
Issho.Participant.place(claude, %{"doc" => "board:42", "at" => %{"node" => "n7"}})
Issho.Participant.lock(claude, [%{"doc" => "board:42", "at" => %{"node" => "n7"}}])
{:ok, _receipt} = Issho.Participant.transact(claude, "board:42", ops)
Issho.Participant.leave(claude)A participant is a process linked to the one that joins. It forwards
what happens in the room to that process (or to :notify) as
{Issho.Participant, participant, event, payload} messages: "tx",
"aware", "presence_diff" and "bye", as a browser receives them,
and, with events: true, "event": the room's events
(Issho.Event), but those the participant made happen itself.
transact/3 takes a list of operations (Issho builds the envelope, on
the latest revision) or a whole transaction map, to retry one with its
original id.
Present, paused, stopped
A participant is a state machine (:gen_statem): present in the room,
or paused or stopped by a person (Issho.Work). Paused or stopped, it
changes nothing: each transaction is refused whole ({:error, {:interrupted, by}}), so nothing is half done, and its task says who
paused or stopped it. It reads, looks and leaves as ever. A resume makes
it present again; so does finishing its task (a pause or a stop), or
beginning another (a stop).
Summary
Functions
Whether the room's policy lets the participant do action (:read,
:write, :lock or your own) now: for a component whose data is not
in Issho's documents, such as a grid of your database, which writes it
itself. A write needs a participant that writes (can: :write).
Merges keys into the participant's awareness state ("status", your own).
Merges a component's own keys into the participant's state, under its
document ("blocks", see Issho.Awareness); a key set to nil goes.
The participant's own awareness state: its place, its locks, its status.
The participant's identity in the room: who it is, and whom it acts for.
Whether someone paused or stopped the participant in the room
(Issho.Work): %{"action" => "pause" | "stop", "by" => person}, or
nil. While it is, its transactions are refused.
The participant's key in the room (its identity's).
Leaves the room.
Sets the places the participant locks ([] releases them).
The places locked in the room by anyone, each with its holder's key.
Opens a document of the room; gives its snapshot.
The people of the room now (Phoenix.Presence's list, by actor key),
each with where they are: %{key => %{"person" => meta, "places" => [place], "states" => [state]}}, a place for each of their sessions
that has one, and each session's whole awareness state (a component's
own keys: a canvas's selection, say).
Sets the participant's place (nil for none), keeping its locks.
The document's current snapshot.
The room of the participant.
Commits operations, or a whole transaction, to an open document.
Functions
@spec authorize(GenServer.server(), atom()) :: :ok | {:error, term()}
Whether the room's policy lets the participant do action (:read,
:write, :lock or your own) now: for a component whose data is not
in Issho's documents, such as a grid of your database, which writes it
itself. A write needs a participant that writes (can: :write).
@spec aware(GenServer.server(), map()) :: :ok | {:error, term()}
Merges keys into the participant's awareness state ("status", your own).
@spec aware_block(GenServer.server(), String.t(), map()) :: :ok | {:error, term()}
Merges a component's own keys into the participant's state, under its
document ("blocks", see Issho.Awareness); a key set to nil goes.
@spec awareness(GenServer.server()) :: map()
The participant's own awareness state: its place, its locks, its status.
@spec identity(GenServer.server()) :: Issho.Identity.t()
The participant's identity in the room: who it is, and whom it acts for.
@spec interrupted(GenServer.server()) :: map() | nil
Whether someone paused or stopped the participant in the room
(Issho.Work): %{"action" => "pause" | "stop", "by" => person}, or
nil. While it is, its transactions are refused.
@spec key(GenServer.server()) :: String.t()
The participant's key in the room (its identity's).
@spec leave(GenServer.server()) :: :ok
Leaves the room.
@spec lock(GenServer.server(), [map()]) :: :ok | {:error, term()}
Sets the places the participant locks ([] releases them).
@spec locks(GenServer.server()) :: [{map(), String.t()}]
The places locked in the room by anyone, each with its holder's key.
@spec open(GenServer.server(), String.t()) :: {:ok, map()} | {:error, term()}
Opens a document of the room; gives its snapshot.
@spec people(GenServer.server()) :: map()
The people of the room now (Phoenix.Presence's list, by actor key),
each with where they are: %{key => %{"person" => meta, "places" => [place], "states" => [state]}}, a place for each of their sessions
that has one, and each session's whole awareness state (a component's
own keys: a canvas's selection, say).
@spec place(GenServer.server(), map() | nil) :: :ok | {:error, term()}
Sets the participant's place (nil for none), keeping its locks.
@spec read(GenServer.server(), String.t()) :: {:ok, map()} | {:error, term()}
The document's current snapshot.
@spec room(GenServer.server()) :: String.t()
The room of the participant.
Commits operations, or a whole transaction, to an open document.