Настройка репликации. Финал #14

This commit is contained in:
2026-05-03 21:02:29 +03:00
parent 3d61830f1c
commit 83ce92afa4
5 changed files with 148 additions and 93 deletions
+45 -19
View File
@@ -8,22 +8,40 @@ start(_StartType, _StartArgs) ->
application:ensure_all_started(cowboy),
case infra_sup:start_link() of
{ok, Pid} ->
% Чтение extra_db_nodes из переменной окружения (если задана)
case os:getenv("MNESIA_EXTRA_DB_NODES") of
false -> ok;
NodesStr ->
Nodes = [list_to_atom(N) || N <- string:tokens(NodesStr, ",")],
% Определяем список узлов кластера, если режим CLUSTER_MODE=true
Nodes = case os:getenv("CLUSTER_MODE", "false") of
"true" ->
DnsName = os:getenv("DNS_NAME", "eventhub-node"),
try inet:getaddrs(DnsName, inet) of
{ok, IPs} when is_list(IPs), IPs /= [] ->
% Получаем имена всех узлов Erlang, зарегистрированных в EPMD
AllNodes = lists:flatmap(fun(IP) ->
case erl_epmd:names(IP) of
{ok, Names} ->
[list_to_atom(Name ++ "@" ++ Name) || {Name, _Port} <- Names,
lists:prefix("eventhub-node", Name)];
_ -> []
end
end, IPs),
% Исключаем свой узел, чтобы не подключаться к самому себе
AllNodes -- [node()];
_ -> []
catch
_:_ ->
io:format("DNS lookup failed, starting as first node~n"),
[]
end;
_ -> []
end,
case Nodes of
[] ->
io:format("Cluster: no nodes found or first node~n");
_ ->
io:format("Cluster: discovered nodes ~p, joining cluster~n", [Nodes]),
application:set_env(eventhub, extra_db_nodes, Nodes)
end,
ok = infra_mnesia:init_tables(),
ok = infra_mnesia:wait_for_tables(),
% Включаем авто‑обнаружение только в режиме remote/swarm
ClusterMode = os:getenv("CLUSTER_MODE", "local"),
case ClusterMode of
"swarm" -> cluster_discovery:discover_and_replicate();
"remote" -> cluster_discovery:discover_and_replicate();
_ -> ok
end,
start_http(), % Пользовательский API (8080)
start_admin_http(), % Административный API (8445)
application:ensure_all_started(prometheus),
@@ -40,7 +58,7 @@ stop(_State) -> ok.
%% Пользовательский HTTP (порт 8080) — только публичные эндпоинты
%% ===================================================================
start_http() ->
Port = application:get_env(eventhub, http_port, 8080),
Port = get_env_int(http_port, 8080),
Dispatch = cowboy_router:compile([
{'_', [
{"/metrics/[:registry]", prometheus_cowboy2_handler, []},
@@ -77,7 +95,7 @@ start_http() ->
%% Административный HTTP (порт 8445) — все админские эндпоинты
%% ===================================================================
start_admin_http() ->
Port = application:get_env(eventhub, admin_http_port, 8445),
PortAdmin = get_env_int(admin_http_port, 8445),
Dispatch = cowboy_router:compile([
{'_', [
% ================== БАЗОВЫЕ ==================
@@ -114,18 +132,20 @@ start_admin_http() ->
Middlewares = [cowboy_router, cowboy_handler],
Env = #{dispatch => Dispatch},
cowboy:start_clear(admin_http, [{port, Port}], #{env => Env, middlewares => Middlewares}),
io:format("Admin HTTP server started on port ~p~n", [Port]),
cowboy:start_clear(admin_http, [{port, PortAdmin}], #{env => Env, middlewares => Middlewares}),
io:format("Admin HTTP server started on port ~p~n", [PortAdmin]),
% WebSocket для пользователей
WsDispatch = cowboy_router:compile([{'_', [{"/ws", ws_handler, []}]}]),
cowboy:start_clear(ws, [{port, 8081}], #{env => #{dispatch => WsDispatch}}),
PortWs = get_env_int(ws_port, 8081),
cowboy:start_clear(ws, [{port, PortWs}], #{env => #{dispatch => WsDispatch}}),
% WebSocket для админов
AdminWsDispatch = cowboy_router:compile([{'_', [{"/admin/ws", admin_ws_handler, []}]}]),
cowboy:start_clear(admin_ws, [{port, 8446}], #{env => #{dispatch => AdminWsDispatch}}),
PortAdminWs = get_env_int(admin_ws_port, 8446),
cowboy:start_clear(admin_ws, [{port, PortAdminWs}], #{env => #{dispatch => AdminWsDispatch}}),
io:format("WebSocket started on ports 8081 (user) and 8446 (admin)~n").
io:format("WebSocket started on ports ~p (user) and ~p (admin)~n", [PortWs, PortAdminWs]).
%% ---------- Инициализация администраторов ----------
init_default_admins() ->
@@ -156,4 +176,10 @@ init_default_admins() ->
io:format("Default support created: ~s~n", [SupportEmail]);
_ ->
io:format("Admins already exist. Skipping creation.~n")
end.
get_env_int(Key, Default) ->
case application:get_env(eventhub, Key, Default) of
Val when is_list(Val) -> list_to_integer(Val);
Val when is_integer(Val) -> Val
end.