Current section
Files
Jump to
Current section
Files
src/gleam@otp@static_supervisor.erl
-module(gleam@otp@static_supervisor).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/gleam/otp/static_supervisor.gleam").
-export([new/1, restart_tolerance/3, auto_shutdown/2, add/2, start/1, supervised/1, init/1, start_child_callback/1]).
-export_type([supervisor/0, strategy/0, auto_shutdown/0, builder/0, erlang_start_flags/0, erlang_start_flag/1, erlang_child_spec/0, erlang_child_spec_property/1, timeout_/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Bindings to Erlang/OTP's `supervisor` module.\n"
"\n"
" For further detail see the Erlang documentation:\n"
" <https://www.erlang.org/doc/apps/stdlib/supervisor.html>.\n"
"\n"
" # Example\n"
"\n"
" ```gleam\n"
" import gleam/erlang/actor\n"
" import gleam/otp/static_supervisor.{type Supervisor} as supervisor\n"
" import app/database_pool\n"
" import app/http_server\n"
" \n"
" pub fn start_supervisor() -> {\n"
" supervisor.new(supervisor.OneForOne)\n"
" |> supervisor.add(database_pool.supervised())\n"
" |> supervisor.add(http_server.supervised())\n"
" |> supervisor.start\n"
" }\n"
" ```\n"
).
-opaque supervisor() :: {supervisor, gleam@erlang@process:pid_()}.
-type strategy() :: one_for_one | one_for_all | rest_for_one.
-type auto_shutdown() :: never | any_significant | all_significant.
-opaque builder() :: {builder,
strategy(),
integer(),
integer(),
auto_shutdown(),
list(gleam@otp@supervision:child_specification(nil))}.
-type erlang_start_flags() :: any().
-type erlang_start_flag(EXY) :: {strategy, strategy()} |
{intensity, integer()} |
{period, integer()} |
{auto_shutdown, auto_shutdown()} |
{gleam_phantom, EXY}.
-type erlang_child_spec() :: any().
-type erlang_child_spec_property(EXZ) :: {id, integer()} |
{start,
{gleam@erlang@atom:atom_(),
gleam@erlang@atom:atom_(),
list(fun(() -> {ok, gleam@otp@actor:started(EXZ)} |
{error, gleam@otp@actor:start_error()}))}} |
{restart, gleam@otp@supervision:restart()} |
{significant, boolean()} |
{type, gleam@erlang@atom:atom_()} |
{shutdown, timeout_()}.
-type timeout_() :: any().
-file("src/gleam/otp/static_supervisor.gleam", 109).
?DOC(" Create a new supervisor builder, ready for further configuration.\n").
-spec new(strategy()) -> builder().
new(Strategy) ->
{builder, Strategy, 2, 5, never, []}.
-file("src/gleam/otp/static_supervisor.gleam", 129).
?DOC(
" To prevent a supervisor from getting into an infinite loop of child\n"
" process terminations and restarts, a maximum restart intensity is\n"
" defined using two integer values specified with keys intensity and\n"
" period in the above map. Assuming the values MaxR for intensity and MaxT\n"
" for period, then, if more than MaxR restarts occur within MaxT seconds,\n"
" the supervisor terminates all child processes and then itself. The\n"
" termination reason for the supervisor itself in that case will be\n"
" shutdown. \n"
"\n"
" Intensity defaults to 1 and period defaults to 5.\n"
).
-spec restart_tolerance(builder(), integer(), integer()) -> builder().
restart_tolerance(Builder, Intensity, Period) ->
_record = Builder,
{builder,
erlang:element(2, _record),
Intensity,
Period,
erlang:element(5, _record),
erlang:element(6, _record)}.
-file("src/gleam/otp/static_supervisor.gleam", 140).
?DOC(
" A supervisor can be configured to automatically shut itself down with\n"
" exit reason shutdown when significant children terminate.\n"
).
-spec auto_shutdown(builder(), auto_shutdown()) -> builder().
auto_shutdown(Builder, Value) ->
_record = Builder,
{builder,
erlang:element(2, _record),
erlang:element(3, _record),
erlang:element(4, _record),
Value,
erlang:element(6, _record)}.
-file("src/gleam/otp/static_supervisor.gleam", 200).
?DOC(" Add a child to the supervisor.\n").
-spec add(builder(), gleam@otp@supervision:child_specification(any())) -> builder().
add(Builder, Child) ->
_record = Builder,
{builder,
erlang:element(2, _record),
erlang:element(3, _record),
erlang:element(4, _record),
erlang:element(5, _record),
[gleam@otp@supervision:map_data(Child, fun(_) -> nil end) |
erlang:element(6, Builder)]}.
-file("src/gleam/otp/static_supervisor.gleam", 207).
-spec convert_child(gleam@otp@supervision:child_specification(any()), integer()) -> erlang_child_spec().
convert_child(Child, Id) ->
Mfa = {erlang:binary_to_atom(<<"gleam@otp@static_supervisor"/utf8>>),
erlang:binary_to_atom(<<"start_child_callback"/utf8>>),
[erlang:element(2, Child)]},
{Type_, Shutdown} = case erlang:element(5, Child) of
supervisor ->
{erlang:binary_to_atom(<<"supervisor"/utf8>>),
gleam_otp_external:make_timeout(-1)};
{worker, Ms} ->
{erlang:binary_to_atom(<<"worker"/utf8>>),
gleam_otp_external:make_timeout(Ms)}
end,
maps:from_list(
[{id, Id},
{start, Mfa},
{restart, erlang:element(3, Child)},
{significant, erlang:element(4, Child)},
{type, Type_},
{shutdown, Shutdown}]
).
-file("src/gleam/otp/static_supervisor.gleam", 157).
?DOC(
" Start a new supervisor process with the configuration and children\n"
" specified within the builder.\n"
"\n"
" Typically you would use the `supervised` function to add your supervisor to\n"
" a supervision tree instead of using this function directly.\n"
"\n"
" The supervisor will be linked to the parent process that calls this\n"
" function.\n"
"\n"
" If any child fails to start the supevisor first terminates all already\n"
" started child processes with reason shutdown and then terminate itself and\n"
" returns an error.\n"
).
-spec start(builder()) -> {ok, gleam@otp@actor:started(supervisor())} |
{error, gleam@otp@actor:start_error()}.
start(Builder) ->
Flags = maps:from_list(
[{strategy, erlang:element(2, Builder)},
{intensity, erlang:element(3, Builder)},
{period, erlang:element(4, Builder)},
{auto_shutdown, erlang:element(5, Builder)}]
),
Module = erlang:binary_to_atom(<<"gleam@otp@static_supervisor"/utf8>>),
Children = begin
_pipe = erlang:element(6, Builder),
_pipe@1 = lists:reverse(_pipe),
gleam@list:index_map(_pipe@1, fun convert_child/2)
end,
case supervisor:start_link(Module, {Flags, Children}) of
{ok, Pid} ->
{ok, {started, Pid, {supervisor, Pid}}};
{error, Error} ->
{error, gleam_otp_external:convert_erlang_start_error(Error)}
end.
-file("src/gleam/otp/static_supervisor.gleam", 186).
?DOC(
" Create a `ChildSpecification` that adds this supervisor as the child of\n"
" another, making it fault tolerant and part of the application's supervision\n"
" tree. You should prefer to starting unsupervised supervisors with the\n"
" `start` function.\n"
"\n"
" If any child fails to start the supevisor first terminates all already\n"
" started child processes with reason shutdown and then terminate itself and\n"
" returns an error.\n"
).
-spec supervised(builder()) -> gleam@otp@supervision:child_specification(supervisor()).
supervised(Builder) ->
gleam@otp@supervision:supervisor(fun() -> start(Builder) end).
-file("src/gleam/otp/static_supervisor.gleam", 269).
?DOC(false).
-spec init(gleam@dynamic:dynamic_()) -> {ok, gleam@dynamic:dynamic_()} |
{error, any()}.
init(Start_data) ->
{ok, Start_data}.
-file("src/gleam/otp/static_supervisor.gleam", 275).
?DOC(false).
-spec start_child_callback(
fun(() -> {ok, gleam@otp@actor:started(any())} |
{error, gleam@otp@actor:start_error()})
) -> {ok, gleam@erlang@process:pid_()} | {error, gleam@otp@actor:start_error()}.
start_child_callback(Start) ->
case Start() of
{ok, Started} ->
{ok, erlang:element(2, Started)};
{error, Error} ->
{error, Error}
end.