Packages

macula

0.27.0
7.0.0 6.0.0 5.2.2 5.2.1 5.2.0 5.1.0 5.0.0 4.8.0 4.7.1 4.7.0 4.6.0 4.5.0 4.4.10 4.4.9 4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.1 4.3.0 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.1 4.1.0 4.0.0 3.16.0 3.15.3 3.15.2 3.15.1 3.14.0 3.13.0 3.12.1 3.12.0 3.11.1 3.11.0 3.10.3 3.10.2 3.10.1 3.9.0 3.8.0 3.7.0 3.5.0 3.4.0 3.3.0 3.2.0 3.1.0 3.0.0 2.1.1 2.1.0 2.0.0 1.5.2 1.5.1 1.4.30 1.4.29 1.4.28 1.4.27 1.4.26 1.4.25 1.4.24 1.4.23 1.4.22 1.4.21 1.4.20 1.4.19 1.4.18 1.4.17 1.4.16 1.4.15 1.4.14 1.4.13 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.1 1.3.0 1.2.0 1.1.0 1.0.10 1.0.9 1.0.8 1.0.7 1.0.6 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 1.0.0 0.48.6 0.48.5 0.48.4 0.48.3 0.48.2 0.48.1 0.48.0 0.47.1 0.47.0 0.46.3 0.46.1 0.46.0 0.45.3 0.45.2 0.45.1 0.45.0 0.44.2 0.44.1 0.44.0 0.43.3 0.43.2 0.43.1 0.43.0 0.42.9 0.42.8 0.42.7 0.42.6 0.42.5 0.42.4 0.42.3 0.42.2 0.42.1 0.42.0 0.41.1 0.41.0 0.40.1 0.40.0 0.39.9 0.39.8 0.39.7 0.39.6 0.39.5 0.39.4 0.39.3 0.39.2 0.39.1 0.39.0 0.38.8 0.38.7 0.38.6 0.38.5 0.38.4 0.38.3 0.38.2 0.38.1 0.38.0 0.37.7 0.37.6 0.37.5 0.37.4 0.37.3 0.37.2 0.37.1 0.37.0 0.36.6 0.36.5 0.36.4 0.36.3 0.36.2 0.36.1 0.36.0 0.35.4 0.35.3 0.35.2 0.35.1 0.35.0 0.34.1 0.34.0 0.33.1 0.33.0 0.32.5 0.32.4 0.32.3 0.32.2 0.32.1 0.32.0 0.31.9 0.31.8 0.31.7 0.31.6 0.31.5 0.31.4 0.31.3 0.31.2 0.31.1 0.31.0 0.30.10 0.30.9 0.30.8 0.30.7 0.30.6 0.30.5 0.30.4 0.30.3 0.30.2 0.30.1 0.30.0 0.29.0 0.28.3 0.28.2 0.28.1 0.28.0 0.27.1 0.27.0 0.26.1 0.26.0 0.25.6 0.25.5 0.25.4 0.25.3 0.25.2 0.25.1 0.25.0 0.24.6 0.24.5 0.24.4 0.24.3 0.24.2 0.24.1 0.24.0 0.23.3 0.23.2 0.23.1 0.23.0 0.22.12 0.22.11 0.22.10 0.22.9 0.22.8 0.22.7 0.22.6 0.22.5 0.22.4 0.22.3 0.22.2 0.22.1 0.22.0 0.21.7 0.21.6 0.21.5 0.21.4 0.21.2 0.21.1 0.21.0 0.20.25 0.20.24 0.20.23 0.20.22 0.20.21 0.20.20 0.20.19 0.20.18 0.20.17 0.20.16 0.20.15 0.20.14 0.20.13 0.20.12 0.20.11 0.20.10 0.20.9 0.20.8 0.20.7 0.20.6 0.20.5 0.20.3 0.20.2 0.20.1 0.20.0 0.19.2 0.19.1 0.19.0 0.18.1 0.18.0 0.17.4 0.17.3 0.17.2 0.17.1 0.17.0 0.16.6 0.16.5 0.16.4 0.16.3 0.16.2 0.16.1 0.16.0 0.15.1 0.15.0 0.14.3 0.14.2 0.14.1 0.14.0 0.12.6 0.12.5 0.12.3 0.11.3 0.10.2 0.10.1 0.10.0 0.9.2 0.9.1 0.9.0 0.8.25 0.8.24 0.8.23 0.8.22 0.8.21 0.8.20 0.8.19 0.8.18 0.8.17 0.8.16 0.8.15 0.8.14 0.8.13 0.8.12 0.8.11 0.8.10 0.8.9 0.8.8 0.8.7 0.8.6 0.8.5 0.8.4 0.8.3 0.8.2 0.8.1 0.8.0 0.7.30 0.7.29 0.7.28 0.7.27 0.7.26 0.7.25 0.7.24 0.7.23 0.7.22 0.7.21 0.7.20 0.7.19 0.7.18 0.7.17 0.7.16 0.7.15 0.7.14 0.7.13 0.7.12 0.7.11 0.7.10 0.7.9 0.7.8 0.7.7 0.7.6 0.7.5 0.7.4 0.7.3 0.7.2 0.7.1 0.7.0 0.6.7 0.6.6 0.6.5 0.6.4 0.6.3 0.6.2 0.6.1 0.6.0 0.5.0 0.4.4 0.4.3 0.4.2 0.4.1 0.4.0 0.3.4 0.3.3 0.3.2 0.3.1

Macula HTTP/3 Mesh SDK — connect, subscribe, publish, call, advertise

Current section

Files

Jump to
macula src macula_bootstrap_system macula_bootstrap_registry.erl
Raw

src/macula_bootstrap_system/macula_bootstrap_registry.erl

%%%-------------------------------------------------------------------
%%% @doc
%%% Bootstrap Registry - Thin wrapper around macula_routing_server DHT.
%%%
%%% Delegates all storage/lookup operations to the DHT routing server.
%%% Bootstrap nodes use the DHT's built-in key-value storage for:
%%% 1. RPC Services - Advertised RPC endpoints
%%% 2. Pub/Sub Topics - Topic subscriptions
%%%
%%% The DHT routing_server handles storage, TTL, and cleanup internally.
%%%
%%% @end
%%%-------------------------------------------------------------------
-module(macula_bootstrap_registry).
-behaviour(gen_server).
-export([start_link/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([
store_service/2, lookup_service/1,
store_topic/2, lookup_topic/1,
store/2, lookup/1, delete/1 % Generic API
]).
-include_lib("kernel/include/logger.hrl").
-record(state, {
routing_server :: pid() % DHT routing server PID
}).
%%%===================================================================
%%% API
%%%===================================================================
-spec start_link(Config :: map()) -> {ok, pid()} | {error, term()}.
start_link(Config) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, Config, []).
%% @doc Store RPC service registration (delegates to DHT)
-spec store_service(Key :: binary(), Value :: term()) -> ok.
store_service(Key, Value) ->
gen_server:call(?MODULE, {store, Key, Value}).
%% @doc Lookup RPC service by key (delegates to DHT)
-spec lookup_service(Key :: binary()) -> {ok, term()} | {error, not_found}.
lookup_service(Key) ->
gen_server:call(?MODULE, {lookup, Key}).
%% @doc Store pub/sub topic subscription (delegates to DHT)
-spec store_topic(Topic :: binary(), Subscriber :: map()) -> ok.
store_topic(Topic, Subscriber) ->
gen_server:call(?MODULE, {store, Topic, Subscriber}).
%% @doc Lookup subscribers for a topic (delegates to DHT)
-spec lookup_topic(Topic :: binary()) -> {ok, [map()]} | {error, not_found}.
lookup_topic(Topic) ->
gen_server:call(?MODULE, {lookup, Topic}).
%% @doc Generic store (delegates to DHT)
-spec store(Key :: binary(), Value :: term()) -> ok.
store(Key, Value) ->
gen_server:call(?MODULE, {store, Key, Value}).
%% @doc Generic lookup (delegates to DHT)
-spec lookup(Key :: binary()) -> {ok, term()} | {error, not_found}.
lookup(Key) ->
gen_server:call(?MODULE, {lookup, Key}).
%% @doc Generic delete (delegates to DHT)
-spec delete(Key :: binary()) -> ok | {error, not_found}.
delete(Key) ->
gen_server:call(?MODULE, {delete, Key}).
%%%===================================================================
%%% GenServer Callbacks
%%%===================================================================
init(_Config) ->
%% Find DHT routing server
case whereis(macula_routing_server) of
undefined ->
?LOG_ERROR("[BootstrapRegistry] DHT routing server not running!"),
{stop, no_routing_server};
RoutingServerPid ->
?LOG_INFO("[BootstrapRegistry] Connected to DHT routing server: ~p", [RoutingServerPid]),
State = #state{
routing_server = RoutingServerPid
},
{ok, State}
end.
%% Store key-value pair in DHT
handle_call({store, Key, Value}, _From, State) ->
RoutingServerPid = State#state.routing_server,
ok = macula_routing_server:store_local(RoutingServerPid, Key, Value),
?LOG_DEBUG("[BootstrapRegistry] Stored in DHT: ~p", [Key]),
{reply, ok, State};
%% Lookup key-value pair in DHT
handle_call({lookup, Key}, _From, State) ->
RoutingServerPid = State#state.routing_server,
case macula_routing_server:get_local(RoutingServerPid, Key) of
{ok, Value} ->
{reply, {ok, Value}, State};
not_found ->
{reply, {error, not_found}, State}
end;
%% Delete key-value pair from DHT
handle_call({delete, Key}, _From, State) ->
RoutingServerPid = State#state.routing_server,
%% Check if exists first, then delete
case macula_routing_server:get_local(RoutingServerPid, Key) of
{ok, _Value} ->
%% Delete using the local node ID (empty binary means delete all)
ok = macula_routing_server:delete_local(RoutingServerPid, Key, <<>>),
?LOG_DEBUG("[BootstrapRegistry] Deleted from DHT: ~p", [Key]),
{reply, ok, State};
not_found ->
{reply, {error, not_found}, State}
end;
handle_call(_Request, _From, State) ->
{reply, {error, unknown_request}, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
%% No cleanup needed - DHT routing server handles storage
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.