erlang: supervisor one-for-one (+7 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
2026-04-25 05:09:41 +00:00
parent 8717094e74
commit 47a59343a1
5 changed files with 137 additions and 6 deletions

View File

@@ -869,3 +869,58 @@
(define
er-load-gen-server!
(fn () (erlang-load-module er-gen-server-source)))
;; ── supervisor (OTP-lite, one-for-one) ──────────────────────────
;; Each child spec is `{Id, StartFn}` — `StartFn/0` returns the
;; child's pid. The supervisor `process_flag(trap_exit, true)`,
;; links to every child, and on `{'EXIT', DeadPid, _}` calls the
;; matching `StartFn` to bring up a fresh replacement. Strategy is
;; one-for-one: only the dead child restarts; siblings keep running.
(define
er-supervisor-source
"-module(supervisor).
start_link(Mod, Args) ->
spawn(fun () ->
process_flag(trap_exit, true),
case Mod:init(Args) of
{ok, ChildSpecs} ->
Children = lists:map(
fun (Spec) -> supervisor:start_child(Spec) end,
ChildSpecs),
supervisor:loop(Children)
end
end).
start_child({Id, StartFn}) ->
P = StartFn(),
link(P),
{Id, StartFn, P}.
which_children(Sup) ->
Sup ! {'$sup_which', self()},
receive {'$sup_children', Cs} -> Cs end.
stop(Sup) ->
Sup ! '$sup_stop',
ok.
loop(Children) ->
receive
{'EXIT', Dead, _Reason} ->
supervisor:loop(supervisor:restart(Children, Dead));
{'$sup_which', From} ->
From ! {'$sup_children', Children},
supervisor:loop(Children);
'$sup_stop' ->
ok
end.
restart([], _) -> [];
restart([{Id, SF, P} | T], Dead) ->
case P =:= Dead of
true ->
NewP = SF(),
link(NewP),
[{Id, SF, NewP} | T];
false ->
[{Id, SF, P} | supervisor:restart(T, Dead)]
end.")
(define
er-load-supervisor!
(fn () (erlang-load-module er-supervisor-source)))