Packages

Elects master node from Erlang/Elixir cluster that is agreed by all nodes.

Current section

Files

Jump to
elector src strategy elector_strategy_behaviour.erl
Raw

src/strategy/elector_strategy_behaviour.erl

%%%-----------------------------------------------------------------------------
%% @doc Defines the base behaviour for election strategies.
%% @end
%%%-----------------------------------------------------------------------------
-module(elector_strategy_behaviour).
%%------------------------------------------------------------------------------
%% Callbacks
%%------------------------------------------------------------------------------
-callback elect(CandidateNodes :: candidate_nodes()) -> Leader :: leader().
%%------------------------------------------------------------------------------
%% Exported API
%%------------------------------------------------------------------------------
-export([elect/0, candidate_nodes/0]).
%%------------------------------------------------------------------------------
%% Type definitions
%%------------------------------------------------------------------------------
-type leader() :: node().
-type candidate_nodes() :: [node()].
%%------------------------------------------------------------------------------
%% Exported functions
%%------------------------------------------------------------------------------
%% @doc Starts the election process by triggering the strategy
%% modules elect() function.
%% The election implementation should only contain the logic for
%% selecting the leader node and returning the leader node name.
%% The elect/0 function is triggered on all nodes automatically
%% by the elector application. This means the strategy implementation
%% does not have to worry about starting the election on all nodes.
%% @end
-spec elect() -> Leader :: leader().
elect() ->
CandidateNodes = candidate_nodes(),
erlang:apply(
elector_config_handler:strategy_module(), elect, [CandidateNodes]
).
%% @doc Returns a list of nodes that are eligible to become the leader.
%% @end
-spec candidate_nodes() -> CandidateNodes :: candidate_nodes().
candidate_nodes() ->
%% SMART CACHED SOLUTION: Use distributed candidate cache
%% This eliminates ALL remote calls and :undef errors while respecting candidate_node config
try
elector_candidate_cache:get_candidates()
catch
_:_ ->
%% Fallback if cache is not available - only return local node if it's a candidate
case erlang:whereis(elector_candidate) of
undefined ->
[];
Pid when is_pid(Pid) ->
case erlang:is_process_alive(Pid) of
true ->
try gen_server:call(Pid, is_candidate_node, 300) of
{ok, true} -> [node()];
_ -> []
catch
_:_ -> []
end;
false ->
[]
end;
_ ->
[]
end
end.