Packages
Typed distributed messaging for Gleam on the BEAM.
Current section
Files
Jump to
Current section
Files
src/config_ffi.erl
-module(config_ffi).
-export([put_config/1, get_config/1, reset_config/0,
put_atom_budget/1,
put_conflict_resolver_timeout/1,
get_conflict_resolver_timeout/0]).
%% Atom keys in persistent_term are never exposed to the Gleam side.
-define(KEY, distribute_config).
-define(BUDGET_VALUE_KEY, distribute_atom_budget).
-define(CONFLICT_TIMEOUT_KEY, distribute_conflict_resolver_timeout).
-define(DEFAULT_CONFLICT_TIMEOUT_MS, 1000).
%% Store config. persistent_term:put/2 is O(1) to read but
%% invalidates per-process heap copies on write. Call once at startup.
put_config(Config) ->
case persistent_term:get(?KEY, nil) of
nil ->
persistent_term:put(?KEY, Config),
{ok, nil};
_ ->
{error, already_configured}
end.
%% Read config, returning Default if not yet configured.
get_config(Default) ->
persistent_term:get(?KEY, Default).
%% Atom budget setter written as a separate persistent_term slot
%% so the FFI atom helpers can read it without decoding the Gleam
%% Config tuple. Called from Gleam-side `configure` after the main
%% Config write succeeds.
put_atom_budget(N) when is_integer(N), N > 0 ->
persistent_term:put(?BUDGET_VALUE_KEY, N),
nil.
%% Conflict-resolver timeout setter uses a separate persistent_term slot
%% so `conflict_ffi:safe_invoke/5` can read the deadline without
%% decoding the Gleam Config tuple. Called from Gleam-side
%% `configure` after the main Config write succeeds.
put_conflict_resolver_timeout(N) when is_integer(N), N > 0 ->
persistent_term:put(?CONFLICT_TIMEOUT_KEY, N),
nil.
%% Read the configured conflict-resolver deadline. Returns the
%% built-in default (1 000 ms) if `configure/1` has not been
%% called. Mirrors `config:default()` so an unconfigured node
%% has the same timeout as a freshly-configured one.
get_conflict_resolver_timeout() ->
persistent_term:get(?CONFLICT_TIMEOUT_KEY, ?DEFAULT_CONFLICT_TIMEOUT_MS).
%% Test utility: clear configuration AND the atom budget counter so
%% we can reconfigure and rerun budget-bounded scenarios.
reset_config() ->
persistent_term:erase(?KEY),
persistent_term:erase(?BUDGET_VALUE_KEY),
persistent_term:erase(?CONFLICT_TIMEOUT_KEY),
distribute_ffi_utils:atom_budget_reset(),
nil.