Packages

Typed distributed messaging for Gleam on the BEAM.

Retired package: Deprecated - The project needs to be redesigned around a much smaller and clearer core.

Current section

Files

Jump to
distribute src distribute@election@raft_lite.erl
Raw

src/distribute@election@raft_lite.erl

-module(distribute@election@raft_lite).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/distribute/election/raft_lite.gleam").
-export([start_service/0, stop_service/0, current_term/0, am_i_leader/0, start_election/0, request_vote/2, send_heartbeat/1, get_raft_leader/0, elect/0, current_leader/0]).
-export_type([election_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 election_result() :: {leader, binary()} | no_leader.
-file("src/distribute/election/raft_lite.gleam", 39).
?DOC(
" Start the Raft-lite election service.\n"
" This spawns a background process that handles election timeouts and heartbeats.\n"
).
-spec start_service() -> nil.
start_service() ->
raft_ffi:start().
-file("src/distribute/election/raft_lite.gleam", 44).
?DOC(" Stop the Raft-lite election service.\n").
-spec stop_service() -> nil.
stop_service() ->
raft_ffi:stop().
-file("src/distribute/election/raft_lite.gleam", 49).
?DOC(" Get the current election term.\n").
-spec current_term() -> integer().
current_term() ->
raft_ffi:current_term().
-file("src/distribute/election/raft_lite.gleam", 54).
?DOC(" Check if this node is currently the leader.\n").
-spec am_i_leader() -> boolean().
am_i_leader() ->
raft_ffi:am_i_leader().
-file("src/distribute/election/raft_lite.gleam", 59).
?DOC(" Trigger a new election. The node will become a candidate and request votes.\n").
-spec start_election() -> nil.
start_election() ->
raft_ffi:start_election().
-file("src/distribute/election/raft_lite.gleam", 65).
?DOC(
" Request a vote from a peer for the given term and candidate.\n"
" Returns True if the vote was granted.\n"
).
-spec request_vote(integer(), binary()) -> boolean().
request_vote(Term, Candidate) ->
raft_ffi:request_vote(Term, Candidate).
-file("src/distribute/election/raft_lite.gleam", 70).
?DOC(" Send a heartbeat as leader to maintain leadership.\n").
-spec send_heartbeat(binary()) -> nil.
send_heartbeat(Leader) ->
raft_ffi:heartbeat(Leader).
-file("src/distribute/election/raft_lite.gleam", 76).
?DOC(
" Get the current leader from the Raft service.\n"
" Returns the leader node name, or empty string if no leader.\n"
).
-spec get_raft_leader() -> {ok, binary()} | {error, nil}.
get_raft_leader() ->
Leader = raft_ffi:get_leader(),
case Leader of
<<""/utf8>> ->
{error, nil};
_ ->
{ok, Leader}
end.
-file("src/distribute/election/raft_lite.gleam", 98).
?DOC(
" Elect a leader from the current alive members. The election rule is\n"
" deterministic: choose the lexicographically largest node returned by\n"
" `membership.alive()`. Returns `NoLeader` when there are no alive nodes.\n"
).
-spec elect() -> election_result().
elect() ->
Alive = distribute@cluster@membership:alive(),
case Alive of
[] ->
no_leader;
[First | _] ->
case gleam@list:max(Alive, fun gleam@string:compare/2) of
{ok, Leader} ->
{leader, Leader};
{error, _} ->
{leader, First}
end
end.
-file("src/distribute/election/raft_lite.gleam", 112).
?DOC(" Convenience: return the current leader as `Result(String, Nil)`.\n").
-spec current_leader() -> {ok, binary()} | {error, nil}.
current_leader() ->
case elect() of
{leader, N} ->
{ok, N};
no_leader ->
{error, nil}
end.