# `Issho.Participant`
[🔗](https://github.com/hattoriai/issho/blob/v0.4.0/lib/issho/participant.ex#L1)

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).

# `authorize`

```elixir
@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`).

# `aware`

```elixir
@spec aware(GenServer.server(), map()) :: :ok | {:error, term()}
```

Merges keys into the participant's awareness state (`"status"`, your own).

# `aware_block`

```elixir
@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.

# `awareness`

```elixir
@spec awareness(GenServer.server()) :: map()
```

The participant's own awareness state: its place, its locks, its status.

# `identity`

```elixir
@spec identity(GenServer.server()) :: Issho.Identity.t()
```

The participant's identity in the room: who it is, and whom it acts for.

# `interrupted`

```elixir
@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.

# `key`

```elixir
@spec key(GenServer.server()) :: String.t()
```

The participant's key in the room (its identity's).

# `leave`

```elixir
@spec leave(GenServer.server()) :: :ok
```

Leaves the room.

# `lock`

```elixir
@spec lock(GenServer.server(), [map()]) :: :ok | {:error, term()}
```

Sets the places the participant locks (`[]` releases them).

# `locks`

```elixir
@spec locks(GenServer.server()) :: [{map(), String.t()}]
```

The places locked in the room by anyone, each with its holder's key.

# `open`

```elixir
@spec open(GenServer.server(), String.t()) :: {:ok, map()} | {:error, term()}
```

Opens a document of the room; gives its snapshot.

# `people`

```elixir
@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).

# `place`

```elixir
@spec place(GenServer.server(), map() | nil) :: :ok | {:error, term()}
```

Sets the participant's place (`nil` for none), keeping its locks.

# `read`

```elixir
@spec read(GenServer.server(), String.t()) :: {:ok, map()} | {:error, term()}
```

The document's current snapshot.

# `room`

```elixir
@spec room(GenServer.server()) :: String.t()
```

The room of the participant.

# `transact`

```elixir
@spec transact(GenServer.server(), String.t(), [map()] | map()) ::
  {:ok, map()} | {:error, term()}
```

Commits operations, or a whole transaction, to an open document.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
