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

Supervises one instance of the framework from a `%Ankusa.Config{}`. Only the
children for configured roles boot, so the same code runs any role set. The
boundaries between components are durable state (this node's store), not
function calls. The store is node-local, so every role that reads or writes
hooks has to run on the node that holds it.

## Failure domains

The tree is `:rest_for_one`, and what the instance does when a part of it
fails depends on which part:

  * **The core** — the claim stores' breaker table
    (`Ankusa.ClaimCheck.Stores`), the store, the source store and the edge
    subtree (routes, queue writer, quarantine, rate limiter, batchers,
    ingress listener) — is
    what acks hooks. A crash there restarts whatever depends on it: the edge
    restarts with the store it writes to, and everything started after it
    restarts with the edge. A core that keeps crashing exhausts this
    supervisor's budget and the instance stops, for its parent to restart.
  * **Every other domain** — dispatch, archive/storage, store backup,
    lifecycle events, metrics, and the admin, route-admin, claim-check and
    metrics listeners — runs under `Ankusa.Instance.Isolated`. It has its own
    restart budget, and when that is exhausted it is restarted later with
    backoff instead of taking the instance down. A broken sink, a port
    someone else took or a full object store stops that domain, not the edge
    acking hooks; the hooks wait in the store and are dispatched when the
    domain returns.
  * **The registry** — a restart of `Ankusa.Registry` forgets every name an
    instance process registered. `Ankusa.Instance.RegistryWatch` notices and
    stops the instance, so whatever supervises it starts it again, every
    process registered anew.

## Stopping

A stop that should not reset a request in flight runs
`Ankusa.Instance.Drain.run/1` first (both applications do, from `prep_stop/1`):
`/ready` flips to `draining`, the edge's ingress listener (the `:ingress` child
of the edge subtree) closes after the requests it is serving, and the
batchers empty. Then this tree stops in reverse start order: dispatch writes
its outcomes, the backup takes its final checkpoint, the store closes.

# `child_spec`

The child spec for the instance `config` describes. Building it stores the
config (`Ankusa.put_config/1`), so the parent's spec, its supervisor reports
and `:sys.get_status/1` name only the instance, and every (re)start reads the
config back. Build it only for an instance you are about to start: it
replaces that name's stored config.

# `start_link`

```elixir
@spec start_link(Ankusa.Config.t() | atom()) :: Supervisor.on_start()
```

# `store?`

```elixir
@spec store?(Ankusa.Config.t()) :: boolean()
```

Whether this instance runs the node-local store (`Ankusa.Store`) and the audit
trail written into it (`Ankusa.Audit`): any of the `:edge`, `:dispatch` or
`:storage` roles, the admin API (every change it makes is audited), or a
source store that accepts writes.

---

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