erlang: supervisor one-for-one (+7 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -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)))
|
||||
|
||||
Reference in New Issue
Block a user