Packages

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

Current section

Files

Jump to
elector src elector_state.erl
Raw

src/elector_state.erl

%%%-----------------------------------------------------------------------------
%% @doc Main elector state process who's responsibility is to start the
%% election process on start up either syncronously or asyncronously.
%% Also sets up monitoring for node up and down events and triggers
%% automatic election if a node goes down or comes up.
%% @private
%% @end
%%%-----------------------------------------------------------------------------
-module(elector_state).
-include("elector_header.hrl").
%%------------------------------------------------------------------------------
%% Behaviours
%%------------------------------------------------------------------------------
-behaviour(gen_server).
%%------------------------------------------------------------------------------
%% Exported API
%%------------------------------------------------------------------------------
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, handle_continue/2]).
%%------------------------------------------------------------------------------
%% Exported functions
%%------------------------------------------------------------------------------
%% @doc Starts the elector state process.
-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
%%------------------------------------------------------------------------------
%% Callback functions
%%------------------------------------------------------------------------------
init(_) ->
schedule_checkup(),
{ok, #{leader_node => undefined}, {continue, set_leader}}.
handle_continue(set_leader, State) ->
CommissionPid = elector_service:commission_pid(),
LeaderNode =
case CommissionPid of
undefined ->
undefined;
_ ->
gen_server:call({global, elector_commission}, get_leader)
end,
{noreply, maps:put(leader_node, LeaderNode, State)}.
handle_info(leader_checkup, #{leader_node := undefined} = State) ->
schedule_checkup(),
gen_server:cast({global, elector_commission}, start_election),
{noreply, State};
handle_info(leader_checkup, State) ->
schedule_checkup(),
{noreply, State};
handle_info(_Msg, State) ->
{noreply, State}.
handle_call({set_leader, LeaderNode}, _From, State) ->
{reply, ok, maps:put(leader_node, LeaderNode, State)};
handle_call(get_leader, _From, State) ->
{reply, maps:get(leader_node, State), State};
handle_call(clear_leader, _From, State) ->
{reply, {ok, leader_cleared}, maps:put(leader_node, undefined, State)};
handle_call(Msg, _From, State) ->
{reply, Msg, State}.
handle_cast(clear_leader, State) ->
{noreply, maps:put(leader_node, undefined, State)};
handle_cast({set_leader, LeaderNode}, State) ->
{noreply, maps:put(leader_node, LeaderNode, State)};
handle_cast(_msg, state) ->
{noreply, state}.
%%------------------------------------------------------------------------------
%% Internal functions
%%------------------------------------------------------------------------------
%% @private
schedule_checkup() ->
erlang:send_after(?LEADER_CHECKUP_INTERV, self(), leader_checkup).