# `Minga.Buffer.State.Swap`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/buffer/state/swap.ex#L1)

Buffer-owned admission state for crash-recovery swap writes.

The state bounds work to one active preparation and one latest pending
snapshot. Its generation advances on every admission and invalidation, so a
prepared older snapshot cannot publish after newer work becomes authoritative.

# `active_work`

```elixir
@type active_work() :: {snapshot(), pid(), reference()}
```

The active preparation worker: snapshot, worker pid, and monitor.

# `generation`

```elixir
@type generation() :: non_neg_integer()
```

Monotonic swap admission generation.

# `snapshot`

```elixir
@type snapshot() :: {generation(), String.t(), binary()}
```

An admitted buffer snapshot: generation, source path, and content.

# `t`

```elixir
@type t() :: %Minga.Buffer.State.Swap{
  active: active_work() | nil,
  backend: module() | nil,
  backend_options: keyword(),
  directory: String.t() | nil,
  generation: generation(),
  pending: snapshot() | nil,
  timer: reference() | nil,
  timer_start: timer_start(),
  timer_token: reference() | nil
}
```

# `timer_start`

```elixir
@type timer_start() :: (pid(), term(), non_neg_integer() -&gt; reference())
```

Function that starts the debounce timer for an admitted swap.

# `admit`

```elixir
@spec admit(t(), String.t(), binary()) :: {:start, snapshot(), t()} | {:pending, t()}
```

Admits a snapshot, starting it immediately or replacing the latest pending work.

# `backend`

```elixir
@spec backend(t()) :: module()
```

Returns the configured storage backend.

# `backend_options`

```elixir
@spec backend_options(t(), generation()) :: keyword()
```

Returns backend options for a generation, including the swap directory.

# `complete`

```elixir
@spec complete(t(), pid(), generation()) ::
  {:ok, reference(), snapshot() | nil, t()} | :unknown
```

Completes matching active work and returns the latest pending snapshot, if any.

# `complete_monitor`

```elixir
@spec complete_monitor(t(), pid(), reference()) ::
  {:ok, generation(), snapshot() | nil, t()} | :unknown
```

Completes matching active work identified by its process monitor.

# `configured?`

```elixir
@spec configured?(t()) :: boolean()
```

Returns true when this buffer has a configured swap directory.

# `consume_timer`

```elixir
@spec consume_timer(t(), reference()) :: {:ok, t()} | :stale
```

Consumes the matching timer token and rejects stale timer messages.

# `invalidate`

```elixir
@spec invalidate(t()) :: {reference() | nil, active_work() | nil, t()}
```

Invalidates every admitted write and returns resources the Buffer process must revoke.

# `new`

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

Builds swap admission state from Buffer start options.

# `publication_status`

```elixir
@spec publication_status(t(), pid(), generation()) :: :current | :obsolete | :unknown
```

Checks whether a worker's prepared result is still the newest admitted snapshot.

# `schedule`

```elixir
@spec schedule(t(), reference(), reference()) :: t()
```

Records the current debounce timer and its stale-message token.

# `take_timer`

```elixir
@spec take_timer(t()) :: {reference() | nil, t()}
```

Clears the current timer and returns its timer reference for cancellation.

# `timer_start`

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

Returns the configured debounce timer starter.

# `worker_started`

```elixir
@spec worker_started(t(), snapshot(), pid(), reference()) :: t()
```

Records the monitored worker that is preparing an admitted snapshot.

---

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