# `Mead.Ledger.Journal`
[🔗](https://github.com/albertosca/mead/blob/main/lib/mead/ledger/journal.ex#L1)

The pure model of the ledger journal: the counter rows, the ring of the last 100 turns and the dropped count that a sequence of journal events adds up to.

The events are `{:turn, entry}`, with the map the ring holds, `{:forget, session_id}`, `:dropped`, and `{:checkpoint, rows, ring}`, which replaces everything before it with the whole state: every counter row, plus `{:dropped, count}` when it is above zero, and the ring entries oldest first. Replaying the events of a file rebuilds the numbers the ETS tables held. It also serves the rewrite of the file, which is built from the file itself and not from the tables: the tables may already hold an event whose journal record has not been written, and a checkpoint taken from them would count it twice.

A counter row is `{key, turns, failures, input_tokens, output_tokens, duration_ms}`, where the key is `{:session, id}` or `{:route, route, provider}`.

# `counter_row`

```elixir
@type counter_row() ::
  {term(), non_neg_integer(), non_neg_integer(), non_neg_integer(),
   non_neg_integer(), non_neg_integer()}
```

# `entry`

```elixir
@type entry() :: map()
```

# `event`

```elixir
@type event() ::
  {:turn, entry()}
  | {:forget, String.t()}
  | :dropped
  | {:checkpoint, [counter_row() | {:dropped, pos_integer()}], [entry()]}
```

# `t`

```elixir
@type t() :: %Mead.Ledger.Journal{
  dropped: non_neg_integer(),
  ring: [entry()],
  rows: %{required(term()) =&gt; counter_row()}
}
```

# `apply_event`

```elixir
@spec apply_event(t(), event()) :: {:ok, t()} | :error
```

Applies one event to the model.

# `checkpoint`

```elixir
@spec checkpoint(t()) :: event()
```

The checkpoint event that replays to this model.

# `dropped`

```elixir
@spec dropped(t()) :: non_neg_integer()
```

How many unreadable events the model has seen.

# `increments`

```elixir
@spec increments(entry()) ::
  {1, 0 | 1, non_neg_integer(), non_neg_integer(), non_neg_integer()}
```

What one turn adds to a counter row: turns, failures, input tokens, output tokens, ms.

# `new`

```elixir
@spec new() :: t()
```

An empty model.

# `operations`

```elixir
@spec operations(entry()) :: [{pos_integer(), non_neg_integer()}]
```

The `:ets.update_counter/4` operations that add one turn to a counter row.

# `replay`

```elixir
@spec replay([event()]) :: {:ok, t()} | {:error, :corrupt}
```

Adds the events up, or `{:error, :corrupt}` at the first one nobody writes.

# `ring_oldest_first`

```elixir
@spec ring_oldest_first(t()) :: [entry()]
```

The ring entries, oldest first.

# `rows`

```elixir
@spec rows(t()) :: [counter_row()]
```

The counter rows of the model.

---

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