-module(distribute@node_builder). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/distribute/node_builder.gleam"). -export([new/0, with_name/2, with_cookie/2, connect_to/2, with_auto_register/1, start/1]). -export_type([node_builder/0, node_result/0, valid_config/0, startup_result/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. -type node_builder() :: {node_builder, gleam@option:option(binary()), gleam@option:option(binary()), list(binary()), boolean()}. -type node_result() :: {node_result, boolean(), list(binary()), list(binary()), list(binary())}. -type valid_config() :: {valid_config, binary(), binary(), list(binary()), boolean()}. -type startup_result() :: {startup_result, boolean(), list(binary()), list(binary())}. -file("src/distribute/node_builder.gleam", 41). ?DOC(" Create a new node builder with default settings\n"). -spec new() -> node_builder(). new() -> {node_builder, none, none, [], false}. -file("src/distribute/node_builder.gleam", 51). ?DOC(" Set the node name\n"). -spec with_name(node_builder(), binary()) -> node_builder(). with_name(Builder, Name) -> {node_builder, {some, Name}, erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder)}. -file("src/distribute/node_builder.gleam", 56). ?DOC(" Set the cookie\n"). -spec with_cookie(node_builder(), binary()) -> node_builder(). with_cookie(Builder, Cookie) -> {node_builder, erlang:element(2, Builder), {some, Cookie}, erlang:element(4, Builder), erlang:element(5, Builder)}. -file("src/distribute/node_builder.gleam", 61). ?DOC(" Add peers to connect to\n"). -spec connect_to(node_builder(), list(binary())) -> node_builder(). connect_to(Builder, Peers) -> {node_builder, erlang:element(2, Builder), erlang:element(3, Builder), lists:append(erlang:element(4, Builder), Peers), erlang:element(5, Builder)}. -file("src/distribute/node_builder.gleam", 66). ?DOC(" Enable auto-registration of common services\n"). -spec with_auto_register(node_builder()) -> node_builder(). with_auto_register(Builder) -> {node_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), true}. -file("src/distribute/node_builder.gleam", 144). ?DOC(" Validate builder configuration\n"). -spec validate_config(node_builder()) -> {ok, valid_config()} | {error, binary()}. validate_config(Builder) -> case erlang:element(2, Builder) of none -> {error, <<"Node name is required"/utf8>>}; {some, Name} -> case erlang:element(3, Builder) of none -> {error, <<"Cookie is required"/utf8>>}; {some, Cookie} -> {ok, {valid_config, Name, Cookie, erlang:element(4, Builder), erlang:element(5, Builder)}} end end. -file("src/distribute/node_builder.gleam", 174). ?DOC(" Start the node\n"). -spec start_node(valid_config()) -> startup_result(). start_node(Config) -> case distribute@cluster:start_node( erlang:element(2, Config), erlang:element(3, Config) ) of {ok, nil} -> {startup_result, true, [], []}; {error, Error} -> Error_str = case Error of {invalid_node_name, Msg} -> <<"Invalid node name: "/utf8, Msg/binary>>; already_started -> <<"Node already started"/utf8>>; cookie_too_long -> <<"Cookie too long"/utf8>>; {network_error, Msg@1} -> <<"Network error: "/utf8, Msg@1/binary>>; {system_error, Msg@2} -> <<"System error: "/utf8, Msg@2/binary>>; {start_failed, Msg@3} -> <<"Start failed: "/utf8, Msg@3/binary>> end, {startup_result, false, [Error_str], []} end. -file("src/distribute/node_builder.gleam", 201). ?DOC(" Connect to peer nodes\n"). -spec connect_peers(list(binary())) -> list(binary()). connect_peers(Peers) -> gleam@list:fold( Peers, [], fun(Acc, Peer) -> case distribute@cluster:connect(Peer) of {ok, _} -> distribute@log:debug( <<"Connected to peer"/utf8>>, [{<<"peer"/utf8>>, Peer}] ), [Peer | Acc]; {error, _} -> distribute@log:warn( <<"Failed to connect to peer"/utf8>>, [{<<"peer"/utf8>>, Peer}] ), Acc end end ). -file("src/distribute/node_builder.gleam", 217). ?DOC(" Register common services\n"). -spec register_common_services() -> list(binary()). register_common_services() -> Services = [{<<"logger"/utf8>>, <<"log_service"/utf8>>}, {<<"monitor"/utf8>>, <<"monitor_service"/utf8>>}, {<<"election"/utf8>>, <<"election_service"/utf8>>}], gleam@list:fold( Services, [], fun(Acc, Service_pair) -> {Module, Name} = Service_pair, distribute@log:debug( <<"Auto-registered service"/utf8>>, [{<<"name"/utf8>>, Name}, {<<"module"/utf8>>, Module}] ), [Name | Acc] end ). -file("src/distribute/node_builder.gleam", 236). -spec bool_to_string(boolean()) -> binary(). bool_to_string(B) -> case B of true -> <<"true"/utf8>>; false -> <<"false"/utf8>> end. -file("src/distribute/node_builder.gleam", 243). -spec int_to_string(integer()) -> binary(). int_to_string(I) -> case I of 0 -> <<"0"/utf8>>; 1 -> <<"1"/utf8>>; 2 -> <<"2"/utf8>>; 3 -> <<"3"/utf8>>; 4 -> <<"4"/utf8>>; 5 -> <<"5"/utf8>>; _ -> <<"N"/utf8>> end. -file("src/distribute/node_builder.gleam", 71). ?DOC(" Start the node with the configured settings\n"). -spec start(node_builder()) -> {ok, node_result()} | {error, distribute@cluster:start_error()}. start(Builder) -> distribute@log:info( <<"Starting distributed node with builder"/utf8>>, [{<<"has_name"/utf8>>, bool_to_string(gleam@option:is_some(erlang:element(2, Builder)))}, {<<"peer_count"/utf8>>, int_to_string(erlang:length(erlang:element(4, Builder)))}, {<<"auto_register"/utf8>>, bool_to_string(erlang:element(5, Builder))}] ), case validate_config(Builder) of {ok, Valid_config} -> Start_result = start_node(Valid_config), case erlang:element(2, Start_result) of true -> distribute@log:info( <<"Node started successfully"/utf8>>, [{<<"node"/utf8>>, erlang:element(2, Valid_config)}, {<<"connections"/utf8>>, int_to_string( erlang:length( erlang:element(4, Start_result) ) )}] ), case distribute@transport:start_link() of {ok, _} -> distribute@log:info( <<"Transport layer started"/utf8>>, [] ); {error, E} -> distribute@log:error( <<"Failed to start transport layer"/utf8>>, [{<<"error"/utf8>>, gleam@string:inspect(E)}] ) end, Connect_result = connect_peers( erlang:element(4, Valid_config) ), Register_result = case erlang:element(5, Valid_config) of true -> register_common_services(); false -> [] end, Final_result = {node_result, true, Connect_result, Register_result, erlang:element(3, Start_result)}, {ok, Final_result}; false -> distribute@log:error( <<"Failed to start node"/utf8>>, [{<<"errors"/utf8>>, gleam@string:join( erlang:element(3, Start_result), <<", "/utf8>> )}] ), {error, {start_failed, gleam@string:join( erlang:element(3, Start_result), <<", "/utf8>> )}} end; {error, Error} -> distribute@log:error( <<"Configuration validation failed"/utf8>>, [{<<"error"/utf8>>, Error}] ), {error, {invalid_node_name, Error}} end.