Настройка репликации. Часть 1 #14

This commit is contained in:
2026-05-03 14:55:57 +03:00
parent 4fdf380f15
commit 3d61830f1c
6 changed files with 137 additions and 58 deletions

View File

@@ -1,5 +1,5 @@
%% ===================================================================
%% EventHub infra_mnesia (стабильная версия с автоочисткой при fresh старте)
%% EventHub infra_mnesia (финальная рабочая версия, задача #14)
%% ===================================================================
-module(infra_mnesia).
-behaviour(gen_server).
@@ -20,6 +20,9 @@
admin_audit, notification
]).
%% Таблицы, которые должны иметь дисковые копии на каждом узле
-define(DISC_TABLES, ?TABLES -- [session, admin_session]).
-define(TABLE_WAIT_TIMEOUT, 5000).
%% ===================================================================
@@ -43,8 +46,13 @@ init([]) ->
{ok, #{}}.
handle_call(init_tables, _From, State) ->
ok = maybe_recreate_schema(),
ok = ensure_cluster_join(),
ExtraNodes = application:get_env(eventhub, extra_db_nodes, []),
case ExtraNodes of
[] ->
ok = maybe_recreate_schema();
_ ->
ok = join_cluster(ExtraNodes)
end,
lists:foreach(fun create_table/1, ?TABLES),
ok = create_indices(),
{reply, ok, State};
@@ -59,7 +67,7 @@ terminate(_Reason, _State) -> ok.
code_change(_OldVsn, State, _Extra) -> {ok, State}.
%% ===================================================================
%% Проверка директории Mnesia и при необходимости пересоздание схемы
%% Локальное создание схемы (только если нет extra_db_nodes)
%% ===================================================================
maybe_recreate_schema() ->
@@ -81,23 +89,61 @@ maybe_recreate_schema() ->
end.
%% ===================================================================
%% Кластер
%% Присоединение к кластеру добавляет локальные дисковые копии таблиц
%% ===================================================================
ensure_cluster_join() ->
ExtraNodes = application:get_env(eventhub, extra_db_nodes, []),
case ExtraNodes of
[] -> ok;
Nodes ->
ok = mnesia:change_config(extra_db_nodes, Nodes),
case lists:member(node(), mnesia:table_info(schema, disc_copies)) of
false -> mnesia:add_table_copy(schema, node(), disc_copies);
true -> ok
end
join_cluster(Nodes) ->
case mnesia:system_info(is_running) of
yes -> mnesia:stop();
no -> ok
end,
application:set_env(mnesia, extra_db_nodes, Nodes),
mnesia:start(),
ensure_schema_disc(),
% Дожидаемся появления всех таблиц в локальной схеме
wait_for_tables_available(),
lists:foreach(fun add_local_disc_copy/1, ?DISC_TABLES).
wait_for_tables_available() ->
lists:foreach(fun(Tab) ->
wait_for_table(Tab)
end, ?DISC_TABLES).
wait_for_table(Tab) ->
case lists:member(Tab, mnesia:system_info(tables)) of
true -> ok;
false ->
timer:sleep(100),
wait_for_table(Tab)
end.
ensure_schema_disc() ->
case lists:member(node(), mnesia:table_info(schema, disc_copies)) of
false ->
io:format("Changing schema copy to disc...~n"),
case mnesia:change_table_copy_type(schema, node(), disc_copies) of
{atomic, ok} -> ok;
{aborted, {already_exists, _, _}} -> ok;
{aborted, Reason} -> error({failed_schema_disc, Reason})
end;
true -> ok
end.
add_local_disc_copy(Tab) ->
case lists:member(node(), mnesia:table_info(Tab, disc_copies)) of
false ->
io:format("Adding local disc copy of table ~p...~n", [Tab]),
case mnesia:add_table_copy(Tab, node(), disc_copies) of
{atomic, ok} -> ok;
{aborted, {already_exists, _}} -> ok;
{aborted, Reason} ->
io:format("Could not add disc copy for ~p: ~p~n", [Tab, Reason])
end;
true -> ok
end.
%% ===================================================================
%% Создание таблиц
%% Создание / открытие таблиц
%% ===================================================================
create_table(Table) ->