-module(glixir@supervisor). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/glixir/supervisor.gleam"). -export([start_dynamic_supervisor_named/1, start_dynamic_supervisor_named_safe/1, start_dynamic_supervisor/0, child_spec/7, start_dynamic_child/4, terminate_dynamic_child/2, which_dynamic_children/1, count_dynamic_children/1, get_all_dynamic_children/1]). -export_type([dynamic_supervisor/2, child_spec/2, restart_strategy/0, child_type/0, supervisor_error/0, start_child_result/1, child_status/0, child_info/2, child_counts/0, child_operation_error/0, dynamic_supervisor_result/0, dynamic_child_result/0, dynamic_terminate_result/0, get_all_children_result/1]). -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( " Type-safe, bounded DynamicSupervisor interop for Gleam/Elixir\n" "\n" " This module provides a *phantom-typed* interface to Elixir DynamicSupervisor.\n" " All child processes are parameterized by their `args` and `reply` types,\n" " so misuse is a compile error, not a runtime surprise.\n" ). -opaque dynamic_supervisor(EVB, EVC) :: {dynamic_supervisor, gleam@erlang@process:pid_()} | {gleam_phantom, EVB, EVC}. -type child_spec(EVD, EVE) :: {child_spec, binary(), gleam@erlang@atom:atom_(), gleam@erlang@atom:atom_(), EVD, restart_strategy(), integer(), child_type()} | {gleam_phantom, EVE}. -type restart_strategy() :: permanent | temporary | transient. -type child_type() :: worker | supervisor_child. -type supervisor_error() :: {start_error, binary()} | {child_start_error, binary(), binary()} | {child_not_found, binary()} | {already_started, binary()} | {invalid_child_spec, binary()}. -type start_child_result(EVF) :: {child_started, gleam@erlang@process:pid_(), EVF} | {start_child_error, binary()}. -type child_status() :: {child_pid, gleam@erlang@process:pid_()} | child_restarting | child_undefined. -type child_info(EVG, EVH) :: {child_info, binary(), gleam@option:option(gleam@erlang@process:pid_()), child_type(), child_status(), EVG, EVH}. -type child_counts() :: {child_counts, integer(), integer(), integer(), integer()}. -type child_operation_error() :: running | restarting | not_found | simple_one_for_one | {other_error, binary()}. -type dynamic_supervisor_result() :: {dynamic_supervisor_ok, gleam@erlang@process:pid_()} | {dynamic_supervisor_error, gleam@dynamic:dynamic_()}. -type dynamic_child_result() :: {dynamic_start_child_ok, gleam@erlang@process:pid_()} | {dynamic_start_child_error, gleam@dynamic:dynamic_()}. -type dynamic_terminate_result() :: dynamic_terminate_child_ok | {dynamic_terminate_child_error, gleam@dynamic:dynamic_()}. -type get_all_children_result(EVI) :: {get_all_children_ok, list(gleam@erlang@process:subject(EVI))} | {get_all_children_error, gleam@dynamic:dynamic_()}. -file("src/glixir/supervisor.gleam", 151). -spec restart_to_string(restart_strategy()) -> binary(). restart_to_string(R) -> case R of permanent -> <<"permanent"/utf8>>; temporary -> <<"temporary"/utf8>>; transient -> <<"transient"/utf8>> end. -file("src/glixir/supervisor.gleam", 159). -spec child_type_to_string(child_type()) -> binary(). child_type_to_string(T) -> case T of worker -> <<"worker"/utf8>>; supervisor_child -> <<"supervisor"/utf8>> end. -file("src/glixir/supervisor.gleam", 169). ?DOC(" Start a named dynamic supervisor with bounded child types\n"). -spec start_dynamic_supervisor_named(gleam@erlang@atom:atom_()) -> {ok, dynamic_supervisor(any(), any())} | {error, supervisor_error()}. start_dynamic_supervisor_named(Name) -> glixir@utils:debug_log( debug, <<"[supervisor] Starting supervisor: "/utf8, (erlang:atom_to_binary(Name))/binary>> ), case 'Elixir.Glixir.Supervisor':start_dynamic_supervisor_named( erlang:atom_to_binary(Name) ) of {dynamic_supervisor_ok, Pid} -> glixir@utils:debug_log( info, <<"[supervisor] Supervisor started successfully"/utf8>> ), {ok, {dynamic_supervisor, Pid}}; {dynamic_supervisor_error, Reason} -> glixir@utils:debug_log( error, <<"[supervisor] Supervisor start failed"/utf8>> ), {error, {start_error, gleam@string:inspect(Reason)}} end. -file("src/glixir/supervisor.gleam", 194). ?DOC( " SAFE: Start a named dynamic supervisor with string name (no atom creation)\n" " Use this for user-generated names to avoid atom table exhaustion\n" ). -spec start_dynamic_supervisor_named_safe(binary()) -> {ok, dynamic_supervisor(any(), any())} | {error, supervisor_error()}. start_dynamic_supervisor_named_safe(Name) -> glixir@utils:debug_log( debug, <<"[supervisor] Starting supervisor (safe): "/utf8, Name/binary>> ), case 'Elixir.Glixir.Supervisor':start_dynamic_supervisor_named(Name) of {dynamic_supervisor_ok, Pid} -> glixir@utils:debug_log( info, <<"[supervisor] Supervisor started successfully (safe)"/utf8>> ), {ok, {dynamic_supervisor, Pid}}; {dynamic_supervisor_error, Reason} -> glixir@utils:debug_log( error, <<"[supervisor] Supervisor start failed (safe)"/utf8>> ), {error, {start_error, gleam@string:inspect(Reason)}} end. -file("src/glixir/supervisor.gleam", 221). ?DOC(" Start an unnamed dynamic supervisor (no atom creation needed)\n"). -spec start_dynamic_supervisor() -> {ok, dynamic_supervisor(any(), any())} | {error, supervisor_error()}. start_dynamic_supervisor() -> glixir@utils:debug_log( debug, <<"[supervisor] Starting unnamed supervisor"/utf8>> ), case 'Elixir.Glixir.Supervisor':start_dynamic_supervisor_named(<<""/utf8>>) of {dynamic_supervisor_ok, Pid} -> glixir@utils:debug_log( info, <<"[supervisor] Unnamed supervisor started successfully"/utf8>> ), {ok, {dynamic_supervisor, Pid}}; {dynamic_supervisor_error, Reason} -> glixir@utils:debug_log( error, <<"[supervisor] Unnamed supervisor start failed"/utf8>> ), {error, {start_error, gleam@string:inspect(Reason)}} end. -file("src/glixir/supervisor.gleam", 247). ?DOC(" Build a type-safe child spec\n"). -spec child_spec( binary(), binary(), binary(), EWE, restart_strategy(), integer(), child_type() ) -> child_spec(EWE, any()). child_spec(Id, Module, Function, Args, Restart, Shutdown_timeout, Child_type) -> {child_spec, Id, erlang:binary_to_atom(Module), erlang:binary_to_atom(Function), Args, Restart, Shutdown_timeout, Child_type}. -file("src/glixir/supervisor.gleam", 268). ?DOC(" Build a dynamic spec map for Elixir\n"). -spec spec_to_map( binary(), gleam@erlang@atom:atom_(), gleam@erlang@atom:atom_(), list(gleam@dynamic:dynamic_()), restart_strategy(), integer(), child_type() ) -> gleam@dynamic:dynamic_(). spec_to_map(Id, M, F, Args, Restart, Shutdown, Child_type) -> gleam@dynamic:properties( [{gleam_stdlib:identity(<<"id"/utf8>>), gleam_stdlib:identity(Id)}, {gleam_stdlib:identity(<<"start_module"/utf8>>), gleam_stdlib:identity(erlang:atom_to_binary(M))}, {gleam_stdlib:identity(<<"start_function"/utf8>>), gleam_stdlib:identity(erlang:atom_to_binary(F))}, {gleam_stdlib:identity(<<"start_args"/utf8>>), erlang:list_to_tuple(Args)}, {gleam_stdlib:identity(<<"restart"/utf8>>), gleam_stdlib:identity(restart_to_string(Restart))}, {gleam_stdlib:identity(<<"shutdown"/utf8>>), gleam_stdlib:identity(erlang:integer_to_binary(Shutdown))}, {gleam_stdlib:identity(<<"type"/utf8>>), gleam_stdlib:identity(child_type_to_string(Child_type))}] ). -file("src/glixir/supervisor.gleam", 289). ?DOC(" Start a child with typed args and replies\n"). -spec start_dynamic_child( dynamic_supervisor(EWJ, EWK), child_spec(EWJ, EWK), fun((EWJ) -> list(gleam@dynamic:dynamic_())), fun((gleam@dynamic:dynamic_()) -> {ok, EWK} | {error, binary()}) ) -> start_child_result(EWK). start_dynamic_child(Supervisor, Spec, Encode, Decode) -> {dynamic_supervisor, Pid} = Supervisor, {child_spec, Id, M, F, Args, Restart, Timeout, Type_} = Spec, glixir@utils:debug_log( debug, <<"[supervisor] Starting child: "/utf8, Id/binary>> ), Spec_map = spec_to_map(Id, M, F, Encode(Args), Restart, Timeout, Type_), case 'Elixir.Glixir.Supervisor':start_dynamic_child(Pid, Spec_map) of {dynamic_start_child_ok, Child_pid} -> case Decode(gleam_stdlib:identity(<<"ok"/utf8>>)) of {ok, Child_reply} -> glixir@utils:debug_log( info, <<"[supervisor] Child started successfully: "/utf8, Id/binary>> ), {child_started, Child_pid, Child_reply}; {error, E} -> glixir@utils:debug_log( error, <<"[supervisor] Child decode failed: "/utf8, E/binary>> ), {start_child_error, E} end; {dynamic_start_child_error, Reason} -> glixir@utils:debug_log( error, <<"[supervisor] Child start failed: "/utf8, Id/binary>> ), {start_child_error, gleam@string:inspect(Reason)} end. -file("src/glixir/supervisor.gleam", 327). ?DOC(" Terminate a child (by pid)\n"). -spec terminate_dynamic_child( dynamic_supervisor(any(), any()), gleam@erlang@process:pid_() ) -> {ok, nil} | {error, binary()}. terminate_dynamic_child(Supervisor, Child_pid) -> {dynamic_supervisor, Pid} = Supervisor, glixir@utils:debug_log( debug, <<"[supervisor] Terminating child: "/utf8, (gleam@string:inspect(Child_pid))/binary>> ), Ffi_result = 'Elixir.Glixir.Supervisor':terminate_dynamic_child( Pid, Child_pid ), glixir@utils:debug_log( debug, <<"[supervisor] FFI result: "/utf8, (gleam@string:inspect(Ffi_result))/binary>> ), Result_string = gleam@string:inspect(Ffi_result), case Result_string of <<"DynamicTerminateChildOk()"/utf8>> -> glixir@utils:debug_log( info, <<"[supervisor] Child terminated successfully"/utf8>> ), {ok, nil}; _ -> glixir@utils:debug_log( error, <<"[supervisor] Child termination failed"/utf8>> ), {error, <<"FFI returned unexpected result: "/utf8, Result_string/binary>>} end. -file("src/glixir/supervisor.gleam", 363). ?DOC( " Returns all dynamic children as a list of Dynamic.\n" " You might want to write a real decoder for full type-safety!\n" ). -spec which_dynamic_children(dynamic_supervisor(any(), any())) -> list(gleam@dynamic:dynamic_()). which_dynamic_children(Supervisor) -> {dynamic_supervisor, Pid} = Supervisor, glixir@utils:debug_log(debug, <<"[supervisor] Querying children"/utf8>>), Result = 'Elixir.Glixir.Supervisor':which_dynamic_children(Pid), glixir@utils:debug_log( debug, <<<<"[supervisor] Found "/utf8, (erlang:integer_to_binary(erlang:length(Result)))/binary>>/binary, " children"/utf8>> ), Result. -file("src/glixir/supervisor.gleam", 376). -spec count_dynamic_children(dynamic_supervisor(any(), any())) -> {ok, child_counts()} | {error, binary()}. count_dynamic_children(Supervisor) -> Child_counts_decoder = begin gleam@dynamic@decode:field( <<"specs"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Specs) -> gleam@dynamic@decode:field( <<"active"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Active) -> gleam@dynamic@decode:field( <<"supervisors"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Supervisors) -> gleam@dynamic@decode:field( <<"workers"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Workers) -> gleam@dynamic@decode:success( {child_counts, Specs, Active, Supervisors, Workers} ) end ) end ) end ) end ) end, {dynamic_supervisor, Pid} = Supervisor, glixir@utils:debug_log(debug, <<"[supervisor] Counting children"/utf8>>), Result_dynamic = 'Elixir.Glixir.Supervisor':count_dynamic_children(Pid), case gleam@dynamic@decode:run(Result_dynamic, Child_counts_decoder) of {ok, Counts} -> glixir@utils:debug_log( debug, <<"[supervisor] Child counts retrieved successfully"/utf8>> ), {ok, Counts}; {error, Errors} -> glixir@utils:debug_log( error, <<"[supervisor] Child count decode failed"/utf8>> ), {error, <<"decode error: "/utf8, (gleam@string:inspect(Errors))/binary>>} end. -file("src/glixir/supervisor.gleam", 405). -spec get_all_dynamic_children(dynamic_supervisor(any(), EXL)) -> {ok, list(gleam@erlang@process:subject(EXL))} | {error, binary()}. get_all_dynamic_children(Supervisor) -> {dynamic_supervisor, Pid} = Supervisor, glixir@utils:debug_log( debug, <<"[supervisor] Getting all child PIDs"/utf8>> ), case 'Elixir.Glixir.Supervisor':get_all_dynamic_children(Pid) of {get_all_children_ok, Pids} -> glixir@utils:debug_log( debug, <<<<"[supervisor] Retrieved "/utf8, (erlang:integer_to_binary(erlang:length(Pids)))/binary>>/binary, " child PIDs"/utf8>> ), {ok, Pids}; {get_all_children_error, Reason} -> glixir@utils:debug_log( error, <<"[supervisor] Failed to get children"/utf8>> ), {error, gleam@string:inspect(Reason)} end.