# `Aerospike.Cluster.Supervisor`
[🔗](https://github.com/luisgabrielroldan/aerospike_driver/blob/v0.3.1/lib/aerospike/cluster/supervisor.ex#L1)

Top-level supervisor for one named Aerospike cluster.

Starts the table owner, per-node pool supervisor, partition-map writer,
and tend-cycle worker under `rest_for_one` so the blast radius of a crash
matches which process owns what state.

Crash semantics under `rest_for_one`:

  * Tend-cycle crash → only the tend-cycle worker restarts. ETS tables
    survive, the pool supervisor and writer survive, and the restarted
    worker rehydrates its `:ready` flag from the `:meta` table.
  * Writer crash → the tend-cycle worker also restarts (it is after the
    writer). The
    next tend-cycle write would target a dead writer anyway; taking
    the worker with it keeps the cycle consistent.
  * Pool-supervisor crash → writer and tend-cycle worker also restart.
  * Table-owner crash → the whole subtree restarts with fresh tables.

This module only supervises. It does not start pools, does not run
tend cycles, and does not own any application state.

# `auth_mode`

```elixir
@type auth_mode() :: :internal | :external | :pki
```

Authentication mode used during node login.

# `connect_option`

```elixir
@type connect_option() ::
  {:connect_timeout_ms, pos_integer()}
  | {:info_timeout, pos_integer()}
  | {:login_timeout_ms, pos_integer()}
  | {:tcp_nodelay, boolean()}
  | {:tcp_keepalive, boolean()}
  | {:tcp_sndbuf, pos_integer() | nil}
  | {:tcp_rcvbuf, pos_integer() | nil}
  | {:tls_name, String.t() | nil}
  | {:tls_cacertfile, Path.t() | nil}
  | {:tls_certfile, Path.t() | nil}
  | {:tls_keyfile, Path.t() | nil}
  | {:tls_verify, :verify_peer | :verify_none}
  | {:tls_opts, keyword()}
  | {atom(), term()}
```

Transport connection option accepted inside startup `:connect_opts`.

TCP transports use the timeout and socket tuning keys. TLS transports
also use the `:tls_*` keys. Auth credentials are configured as top-level
startup options; the Tender forwards derived auth/session values to
transports internally. Other atom keys are forwarded to custom
transports and ignored by the built-in transports.

# `connect_options`

```elixir
@type connect_options() :: [connect_option()]
```

Keyword list of transport connection options.

# `option`

```elixir
@type option() ::
  {:name, atom()}
  | {:transport, module()}
  | {:hosts, [String.t(), ...]}
  | {:namespaces, [String.t(), ...]}
  | {:connect_opts, connect_options()}
  | {:pool_size, pos_integer()}
  | {:min_connections_per_node, non_neg_integer()}
  | {:idle_timeout_ms, pos_integer()}
  | {:max_idle_pings, pos_integer()}
  | {:tend_interval_ms, pos_integer()}
  | {:tend_trigger, tend_trigger()}
  | {:failure_threshold, non_neg_integer()}
  | {:circuit_open_threshold, non_neg_integer()}
  | {:max_concurrent_ops_per_node, pos_integer()}
  | {:max_retries, non_neg_integer()}
  | {:sleep_between_retries_ms, non_neg_integer()}
  | {:replica_policy, Aerospike.RetryPolicy.replica_policy()}
  | {:use_compression, boolean()}
  | {:use_services_alternate, boolean()}
  | {:seed_only_cluster, boolean()}
  | {:cluster_name, String.t()}
  | {:application_id, String.t()}
  | {:auth_mode, auth_mode()}
  | {:user, String.t()}
  | {:password, String.t()}
  | {:login_timeout_ms, pos_integer()}
```

Startup option accepted by `Aerospike.start_link/1` and
`Aerospike.child_spec/1`.

  * `:name` — atom used as the cluster identity (required). Becomes
    the cluster process name, table prefix, and pool-supervisor name.
  * `:transport` — module implementing `Aerospike.Cluster.NodeTransport`
    (required).
  * `:hosts` — list of `"host:port"` or `"host"` seed strings
    (required, non-empty).
  * `:namespaces` — list of namespace strings the cluster must serve
    before `Aerospike.Cluster.ready?/1` returns `true` (required,
    non-empty).

Pool-level knobs live at the top level of the keyword list because
the pool supervisor, not the transport, applies them. TCP and TLS tuning
knobs live inside `:connect_opts` because the transport owns socket setup.

Pool and lifecycle keys:

  * `:pool_size` — workers per node. Positive integer.
  * `:min_connections_per_node` — warm connection target per node.
    Non-negative integer.
  * `:idle_timeout_ms` — idle worker eviction timeout in milliseconds.
    Positive integer.
  * `:max_idle_pings` — maximum idle workers dropped per verification
    cycle. Positive integer.
  * `:tend_interval_ms` — automatic tend period in milliseconds.
    Positive integer.
  * `:tend_trigger` — `:timer` or `:manual`.

Breaker and command-default keys:

  * `:failure_threshold` — consecutive tend failures before node
    demotion. Non-negative integer.
  * `:circuit_open_threshold` — consecutive node failures before the
    breaker refuses commands. Non-negative integer.
  * `:max_concurrent_ops_per_node` — per-node in-flight plus queued
    command cap. Positive integer.
  * `:max_retries`, `:sleep_between_retries_ms`, `:replica_policy` —
    default retry policy. See `t:Aerospike.RetryPolicy.option/0`.
  * `:use_compression` — cluster-wide request compression opt-in.

Discovery and identity keys:

  * `:use_services_alternate` — use alternate peer endpoints during
    discovery.
  * `:seed_only_cluster` — skip peer discovery and use only configured
    seeds.
  * `:cluster_name` — expected server cluster name.
  * `:application_id` — client application identity sent to supporting
    servers.

`:user` and `:password` are cluster-wide session-login credentials. Both
must be present together; neither present disables auth. PKI auth uses the
TLS client certificate and must omit both.

# `options`

```elixir
@type options() :: [option()]
```

Keyword list of startup options.

# `tend_trigger`

```elixir
@type tend_trigger() :: :timer | :manual
```

Cluster tend scheduling mode.

# `child_spec`

```elixir
@spec child_spec(options()) :: Supervisor.child_spec()
```

Returns the OTP child specification for one named Aerospike cluster.

Accepted options are documented by `t:option/0`.

# `start_link`

```elixir
@spec start_link(options()) :: Supervisor.on_start()
```

Starts the top-level supervisor for one named cluster.

Returns the `Supervisor` pid on success. The supervisor registers
itself under `sup_name/1` so callers can reach it by name.

Accepted options are documented by `t:option/0`. `:name`,
`:transport`, `:hosts`, and `:namespaces` are required.

# `sup_name`

```elixir
@spec sup_name(atom()) :: atom()
```

Returns the registered name atom used by `start_link/1` for `name`.

---

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