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
Current section
Files
src/distribute@cluster@health.erl
-module(distribute@cluster@health).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/distribute/cluster/health.gleam").
-export([is_healthy/0, node_health/0, cluster_health/0, alive_count/0, suspect_count/0, has_quorum/1, current_leader/0]).
-export_type([cluster_health/0, node_health/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 cluster_health() :: healthy | {degraded, integer(), integer()} | isolated.
-type node_health() :: node_healthy | {node_unhealthy, binary()}.
-file("src/distribute/cluster/health.gleam", 28).
?DOC(
" Check if the local node is healthy.\n"
" A node is considered healthy if:\n"
" - The membership service is running\n"
" - It can see at least one other node (or is intentionally standalone)\n"
).
-spec is_healthy() -> boolean().
is_healthy() ->
Suspects = distribute@cluster@membership:suspect(),
Suspects =:= [].
-file("src/distribute/cluster/health.gleam", 35).
?DOC(" Get detailed health status of the local node.\n").
-spec node_health() -> node_health().
node_health() ->
Suspects = distribute@cluster@membership:suspect(),
case Suspects of
[] ->
node_healthy;
_ ->
{node_unhealthy, <<"Nodes in suspect state"/utf8>>}
end.
-file("src/distribute/cluster/health.gleam", 44).
?DOC(" Get the overall cluster health status.\n").
-spec cluster_health() -> cluster_health().
cluster_health() ->
Members = distribute@cluster@membership:members_with_status(),
Alive_count = erlang:length(gleam@list:filter(Members, fun(M) -> case M of
{_, alive, _} ->
true;
_ ->
false
end end)),
Suspect_count = erlang:length(
gleam@list:filter(Members, fun(M@1) -> case M@1 of
{_, suspect, _} ->
true;
_ ->
false
end end)
),
Dead_count = erlang:length(
gleam@list:filter(Members, fun(M@2) -> case M@2 of
{_, dead, _} ->
true;
_ ->
false
end end)
),
case {Alive_count, Suspect_count, Dead_count} of
{0, 0, 0} ->
isolated;
{_, 0, 0} ->
healthy;
{_, S, D} ->
{degraded, S, D}
end.
-file("src/distribute/cluster/health.gleam", 82).
?DOC(" Get count of alive nodes.\n").
-spec alive_count() -> integer().
alive_count() ->
erlang:length(distribute@cluster@membership:alive()).
-file("src/distribute/cluster/health.gleam", 87).
?DOC(" Get count of suspect nodes.\n").
-spec suspect_count() -> integer().
suspect_count() ->
erlang:length(distribute@cluster@membership:suspect()).
-file("src/distribute/cluster/health.gleam", 93).
?DOC(
" Check if we have quorum (majority of expected nodes alive).\n"
" `expected_nodes` is the total expected cluster size including self.\n"
).
-spec has_quorum(integer()) -> boolean().
has_quorum(Expected_nodes) ->
Alive = alive_count() + 1,
Alive > (Expected_nodes div 2).
-file("src/distribute/cluster/health.gleam", 100).
?DOC(" Get the current leader if available.\n").
-spec current_leader() -> {ok, binary()} | {error, nil}.
current_leader() ->
distribute@cluster@membership:current_leader().