# `Ankusa.Intake.Gate`
[🔗](https://github.com/jamescarr/ankusa/blob/ankusa-v0.7.0/packages/ankusa/lib/ankusa/intake/gate.ex#L1)

The intake breaker of `wal: :dual` (ADR 0002, section 7). Under dual there is
no degraded mode: a node that cannot confirm in the log refuses, it never acks
on local fsync alone.

`closed` admits every batch. It opens after `intake.breaker_failures`
consecutive failed publish attempts, or when the adapter's `ready?/1` says no.
`open` refuses until `intake.probe_ms` has passed, then lets **one** batch
through (`half_open`): its confirm closes the breaker, its failure reopens it.
The probe is a real batch, not a probe record.

The state lives in the pending set's ETS table (`Ankusa.Intake.Pending`), which
the writer reads inside its own process: no `:persistent_term.put`, no call,
nothing on the request path but a table read (ground rule 6).

# `abort_probe`

```elixir
@spec abort_probe(Ankusa.Intake.Pending.table(), integer()) :: :ok
```

The probe batch never published (it turned out to have nothing to publish).

# `admit`

```elixir
@spec admit(Ankusa.Intake.Pending.table(), Ankusa.Config.t(), integer()) ::
  :ok | {:error, :open}
```

`:ok` to publish a batch now, `{:error, :open}` to refuse before touching either half.

# `not_ready`

```elixir
@spec not_ready(Ankusa.Intake.Pending.table(), integer()) :: :ok
```

The adapter says it is not ready: open the breaker (the reconciler's tick).

# `record`

```elixir
@spec record(Ankusa.Intake.Pending.table(), Ankusa.Config.t(), boolean(), integer()) ::
  :ok
```

Records a publish attempt's outcome (`true` = confirmed).

# `state`

```elixir
@spec state(Ankusa.Intake.Pending.table()) :: :closed | :open | :half_open
```

`:closed`, `:open` or `:half_open`.

---

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