B2.1 · dive 3 — the blast radius
These die together — or not.
R4 crashes the portfolio store while the order store holds a position row: sibling untouched (one_for_one) — ord_store pid stable, row intact through prt_store's crash. A restart strategy is a blast-radius statement, and choosing anything wider than one_for_one is a written claim that the named children die together.
Source: content/bcs2.1.md, quoting bcs_rung_2_1_check.out; the
supervisor is committed at lib/echo_data/bcs/supervisor.ex.
EchoData.Bcs.Supervisor, one_for_one over two
named stores — the tree the rung booted. Select the crash to read what R4 recorded.The transcript
bcs_rung_2_1_check.out · verbatim · this dive reads R4 and the boot lineboot: two stores under one_for_one; native codec self-check passed at each init R1 surface ok -- exports: six domain functions plus OTP callbacks, nothing else -- no table, no pid, no internals R2 existence ok -- existence restored, data not: fresh table after kill -- durability is a different chapter's job R4 radius ok -- sibling untouched (one_for_one): ord_store pid stable, row intact through prt_store's crash R3 checkpoint ok -- recovered through the boundary, not the heap: re-put from a read-back row R5 gate ok -- prt_store refuses an ORD name with {:error, :namespace} -- admitted kinds are per-boundary PASS 5/5
Start order is the dependency declaration
content/bcs2.1.md · What/Where · supervisor.exChildren start left to right and stop in reverse [1], so the list in
EchoData.Bcs.Supervisor is documentation the runtime enforces. The supervisor, committed
verbatim:
def init(stores) do
children =
for {name, ns} <- stores do
Supervisor.child_spec({EchoData.Bcs.PropertyStore, [name: name, namespace: ns]},
id: name
)
end
Supervisor.init(children, strategy: :one_for_one)
end
The proper Application callback module arrives with the umbrella adoption
rung, where a Mix project exists to declare it in. Restart intensity defaults (the supervisor's maximum
restart frequency [1]) are untested at their limit here — the gates kill twice, far
under it.
Strategy is a written claim
content/bcs2.1.md · What/When/DecisionsUnder one_for_one, when a child terminates, “only that child process
is affected” [1] — and choosing anything wider is therefore a written claim
that the named children die together. Choose one_for_one by default and depart only with a
written reason: stores with shared startup assumptions earn rest_for_one, and a genuine
die-together cluster earns one_for_all, each departure a sentence in the design, not a flag
in the code. For operators, the supervision tree is the runbook: the strategy column answers “what
cascades,” the start order answers “what depends on what,” and both are code.
store_a, store_b, store_c). Select a strategy and a
crashed child; the readout lists the restart set the strategy declares.Static verdicts, crash store_b: one_for_one →
store_b alone · rest_for_one → store_b, store_c (the
crashed child and every child started after it) · one_for_all →
store_a, store_b, store_c. Crash store_a under rest_for_one
→ all three; crash store_c under rest_for_one →
store_c alone.
The Go counterpart — the supervise loop
content/bcs2.1.md · HowThe application shape translates without OTP: a package whose Start(ctx)
spawns the owner goroutine from Chapter 1.1 and returns a handle of typed methods — the export list,
enforced by the package boundary — and whose supervisor is a restart loop, quoted verbatim:
func supervise(ctx context.Context, run func(context.Context) error) {
backoff := 100 * time.Millisecond
for ctx.Err() == nil {
if err := runRecovering(ctx, run); err != nil {
time.Sleep(backoff) // existence restored next loop;
backoff = min(backoff*2, 2*time.Second)
continue // data was the goroutine's locals: gone, by design
}
return
}
}
Existence guarded by the loop, data by nothing — the same statement R2 gates, made in a
language with no supervisor behaviour. One loop per system is the one_for_one analog; a
shared loop over several owners would be one_for_all and should be exactly as
deliberate.
References
sources · relatedSources
- Erlang/OTP — the supervisor behaviourrestart strategies; start order; maximum restart frequency
- Erlang/OTP — the ets modulethe private table each child owns
Related
- B2.1 — A System Is an OTP Applicationthe module hub; the full rung in context
- B2 — The Elixir BCS Corethe chapter landing; the Part II arc
- BCS — the course homethe law, the id anatomy, the chapter map
- Functional Programming in Elixirthe umbrella where echo_data lives