# `Hyper.Cluster.Scheduler`
[🔗](https://github.com/harmont-dev/hyper/blob/main/lib/hyper/cluster/scheduler.ex#L1)

Picks the node to run a VM on. The first pass reads the gossip-replicated
`Hyper.Node.Budget.NodeState`s (`Hyper.Cluster.Budget.all_states/0`), drops
nodes that cannot fit the spec, and ranks survivors by how many bytes of the
VM's image layers they already have mounted (`colo(N, VM) = sum of |L|` over
shared mounted layers). The result is an ordered candidate list; the chosen
node confirms authoritatively via `Hyper.Node.Budget.admit/2` (see `place/3`).

All filtering is best-effort on a possibly-stale snapshot: a node that no
longer fits simply refuses at confirmation time.

# `layer_sizes`

```elixir
@type layer_sizes() :: [{Hyper.Layer.id(), Unit.Information.t()}]
```

# `candidates`

```elixir
@spec candidates(Hyper.Vm.Instance.Spec.t(), layer_sizes()) :: [node()]
```

Fitting nodes for `spec`, most colocated bytes first.

# `colocation_score`

```elixir
@spec colocation_score(Hyper.Node.Budget.NodeState.t(), layer_sizes()) ::
  non_neg_integer()
```

Bytes of `layers` already mounted on `state`'s node.

# `place`

```elixir
@spec place(Hyper.Vm.Instance.Spec.t(), layer_sizes(), (node() -&gt;
                                                    {:ok, term()}
                                                    | {:error, term()})) ::
  {:ok, {node(), term()}} | {:error, :no_capacity}
```

Place `spec` on the best confirming node.

Walks `candidates/2` in rank order, calling `attempt` on each until one returns
`{:ok, result}` (the authoritative confirmation, typically a node running
`Hyper.Node.try_run/3` over `:erpc`). `{:error, :no_capacity}` if all refuse.

# `run`

```elixir
@spec run(
  Hyper.Vm.Instance.Spec.t(),
  layer_sizes(),
  (-&gt; {:ok, pid()} | {:error, term()}),
  (pid() -&gt;
     :ok)
) ::
  {:ok, {node(), pid()}} | {:error, :no_capacity}
```

Place and boot `spec` somewhere in the cluster.

Confirms each candidate by RPC-ing `Hyper.Node.try_run/3` on it; the first node
to boot the VM and reserve its budget wins. `start_fun`/`stop_fun` describe how
to boot/tear down the VM on the target node.

---

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