# `LangExtract.Runner.Limiter`
[🔗](https://github.com/mdepolli/lang_extract/blob/v0.10.0/lib/lang_extract/runner/limiter.ex#L1)

The runner's shared request budget: an RPM token bucket plus an in-flight
cap, with global backoff on `retry-after`.

Chunk tasks call `acquire/2` before each HTTP request and `release/1`
after it completes. Acquirers are monitored — a killed task (stream halt,
crash) releases its slot automatically, so budget can never leak.
`pause/2` holds *all* admission until a deadline: one 429 informs every
in-flight chunk instead of N requests independently colliding with the
same exhausted window.

Emits `[:lang_extract, :limiter, :wait]` whenever an acquire had to wait,
with the wait `duration`, the `reason` that blocked it first
(`:rpm` | `:in_flight` | `:retry_after`), and the `limiter` pid.

Tokens refill lazily from elapsed time — no timer ticks. The clock is
injectable (`:clock`, a zero-arity fun returning milliseconds) so tests
run on virtual time.

Internal — no stability guarantees; see the README's "Stability"
section. Documented because it explains how the library works, not
because it is API.

# `option`

```elixir
@type option() ::
  {:rpm, pos_integer() | :infinity}
  | {:max_in_flight, pos_integer()}
  | {:clock, (-&gt; integer())}
  | {:name, GenServer.name()}
```

# `acquire`

```elixir
@spec acquire(GenServer.server(), timeout()) :: :ok
```

Blocks until a request slot and a token are granted.

Returns `:ok`. The caller is monitored until it calls `release/1` (or
dies, which releases implicitly).

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `pause`

```elixir
@spec pause(GenServer.server(), non_neg_integer()) :: :ok
```

Pauses all admission for `ms` milliseconds (a `retry-after` deadline).

Repeated pauses extend to the furthest deadline; they never shorten it.

# `release`

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

Releases the caller's in-flight slot after its request completes.

# `start_link`

```elixir
@spec start_link([option()]) :: GenServer.on_start()
```

---

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