Fief.Supervisor (Fief v0.1.0)

Copy Markdown View Source

Root supervisor of one Fief instance — a thin outer supervisor over two children (docs/leave-on-shutdown.md §2.6):

  1. Fief.Kernel — the instance's live machinery, a rest_for_one supervisor whose children and ordering carry the fencing and cache-survival semantics (see its moduledoc). Mounted significant: true, restart: :temporary;
  2. Fief.Node.ShutdownDrain — the shutdown-leave sentinel, appended last and present only under the shape gate below.

Fail-fast: a Fief node going down means this process exits

The outer never restarts the kernel. The kernel is a rest_for_one supervisor with its own restart budget, so by the time the kernel process exits it has already exhausted local recovery; an outer retry would just replay a strategy that just failed. So the kernel is significant and the outer runs auto_shutdown: :any_significant — a kernel exit brings the whole instance down and Fief.Supervisor itself exits (reason :shutdown). A Fief node going down surfaces as its top process exiting; the user's supervision tree decides recovery (restart via a :permanent/:transient child spec, or not). Fief does not hide a sick instance behind a silent internal reboot — the failure path (lease expiry, takeover) is the verified fallback, and a persistently sick node should become visibly dead quickly.

The sentinel sits outside the kernel's restart unit

The split is load-bearing. Were the sentinel a flat tail child of the rest_for_one kernel, an internal sibling crash (a Fief.Vnode.Manager blip) would restart it and deliver terminate(:shutdown, _) while a healthy Fief.Node is still alive — tripping a spurious full graceful drain on a routine local fault. As an outer child it is never terminated for a kernel-internal fault, so the only :shutdown it sees is a genuine teardown of the whole instance. On that teardown the outer terminates children in reverse start order — the sentinel (last) first, its drain running while the kernel is still alive behind it (§2.3); and on a kernel exit that triggers auto_shutdown, the sentinel is likewise terminated first, but the kernel is already gone, so its leave/1 no-ops on a dead node and it returns at once (§2.6, §2.7 — the escalation path is self-gating).

The outer strategy is :one_for_one so a sentinel crash restarts only the (inert) sentinel; the kernel's significant flag, not the strategy, governs what a kernel exit does.

Shutdown leave

leave_on_shutdown: pos_integer() | :infinity | false, default 20_000 ms. When enabled (the default), tearing the instance down — System.stop/0, SIGTERM, application shutdown, or the parent terminating this supervisor — runs Fief.Node.leave/1 and blocks the fall of the tree until the node drains to :stopped or the deadline expires. The value is the sentinel's child-spec shutdown: deadline; there is no second timer. On timeout the supervisor kills the sentinel and the tree falls — a timed-out shutdown is an ordinary node failure (guides/protocols/failure.md), no new failure mode. Per-node tuning, not fingerprinted. Default 20 s sits under the k8s 30 s terminationGracePeriodSeconds so the drain gets a real chance before SIGKILL.

The sentinel is present only when all hold (else there is nothing to drain, or nothing that could ever drain it, so a wait is a guaranteed timeout): leave_on_shutdown is not false; a :vnode_impl is configured; the planner subtree is enabled (leadership is not false); and the instance is not sim-joined. A simulation drives its own lifecycle by stepping scheduler events — there is no OTP-driven graceful shutdown to hook, and a drain during ExUnit teardown could only spin against a quiescent scheduler until the deadline (leave-on-shutdown §3.2).

Summary

Functions

Returns a specification to start this module under a supervisor.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

start_link(opts)