CI/CD: ci, deploy-ift и deploy-stage через EventHubDevOps; фиксы calendar view, archive, API-тесты, traefik-coraza
Deploy IFT (core) / deploy-ift-core (push) Failing after 22m58s
CI / test (push) Failing after 22m59s

This commit is contained in:
2026-07-08 14:50:59 +03:00
parent 4cb6056917
commit f4746df4a2
15 changed files with 247 additions and 53 deletions
+3 -3
View File
@@ -4,9 +4,9 @@
-export([fetch/3]).
fetch(CalendarId, Year, Month) ->
Start = {Year, Month, 1, 0, 0, 0},
End = {Year, Month, 31, 23, 59, 59},
Start = {{Year, Month, 1}, {0, 0, 0}},
End = {{Year, Month, calendar:last_day_of_the_month(Year, Month)}, {23, 59, 59}},
mnesia:dirty_select(event, [{#event{calendar_id = CalendarId,
start_time = '$1', _ = '_'},
[{'>=','$1', Start},{'=<','$1', End}],
[{'>=', '$1', {const, Start}}, {'=<', '$1', {const, End}}],
['$_']}]).
+40 -6
View File
@@ -16,7 +16,7 @@ init([]) ->
{ok, #{}}.
handle_call({get_node, Day}, _From, State) ->
Node = list_to_atom("eventhub_archive_" ++ Day ++ "@" ++ host()),
Node = archive_node_name(Day),
case maps:find(Node, State) of
{ok, _Info} -> % переменная не используется, ок
{reply, {ok, Node}, update_access(State, Node)};
@@ -55,14 +55,48 @@ update_access(State, Node) ->
State#{Node => Info#{timer => Ref, last_access => erlang:monotonic_time()}}.
start_archive_node(Day) ->
Node = list_to_atom("eventhub_archive_" ++ Day ++ "@" ++ host()),
case slave:start(host(), Node) of
Node = archive_node_name(Day),
case start_archive_peer(Node) of
{ok, _} ->
rpc:call(Node, mnesia, start, []),
{ok, Node};
Error -> Error
case ensure_archive_node_ready(Node) of
ok -> {ok, Node};
{error, Reason} -> {error, Reason}
end;
{error, Reason} ->
{error, Reason}
end.
start_archive_peer(Node) ->
case os:getenv("CLUSTER_MODE") of
"true" ->
case peer:start_link(#{name => Node, host => host()}) of
{ok, _} -> {ok, Node};
{error, {already_started, _}} -> {ok, Node};
Error -> Error
end;
_ ->
CookieStr = atom_to_list(erlang:get_cookie()),
case slave:start(host(), Node, "-setcookie " ++ CookieStr) of
{ok, _} -> {ok, Node};
Error -> Error
end
end.
ensure_archive_node_ready(Node) ->
case rpc:call(Node, mnesia, start, [], 5000) of
ok ->
case rpc:call(Node, code, ensure_loaded, [archive_fetcher], 5000) of
{module, archive_fetcher} -> ok;
{error, Reason} -> {error, Reason};
{badrpc, Reason} -> {error, Reason}
end;
{badrpc, Reason} -> {error, Reason};
Other -> {error, Other}
end.
archive_node_name(Day) ->
list_to_atom("eventhub_archive_" ++ Day ++ "@" ++ host()).
stop_archive_node(Node) ->
rpc:cast(Node, init, stop, []).
+24 -4
View File
@@ -14,6 +14,8 @@
-include("records.hrl").
-define(ARCHIVE_CALL_TIMEOUT, 3000).
%%% cowboy_handler callback
-spec init(cowboy_req:req(), any()) -> {ok, cowboy_req:req(), any()}.
init(Req, Opts) ->
@@ -135,10 +137,28 @@ fetch_hot_events(CalendarId, Year, Month) ->
]).
%% @private Извлекает архивные события через RPC на архивный узел.
%% При недоступности архива возвращает события из основной Mnesia.
-spec fetch_archive_events(binary(), integer(), integer()) -> list(#event{}).
fetch_archive_events(CalendarId, Year, Month) ->
DayStr = io_lib:format("~4..0B~2..0B", [Year, Month]),
case archive_manager:get_archive_node(lists:flatten(DayStr)) of
{ok, Node} -> rpc:call(Node, archive_fetcher, fetch, [CalendarId, Year, Month]);
{error, _} -> []
DayStr = lists:flatten(io_lib:format("~4..0B~2..0B", [Year, Month])),
case safe_get_archive_node(DayStr) of
{ok, Node} ->
case rpc:call(Node, archive_fetcher, fetch, [CalendarId, Year, Month],
?ARCHIVE_CALL_TIMEOUT) of
Events when is_list(Events) -> Events;
_ -> fetch_hot_events(CalendarId, Year, Month)
end;
{error, _} ->
fetch_hot_events(CalendarId, Year, Month)
end.
-spec safe_get_archive_node(string()) -> {ok, node()} | {error, term()}.
safe_get_archive_node(Day) ->
try gen_server:call(archive_manager, {get_node, Day}, ?ARCHIVE_CALL_TIMEOUT) of
{ok, Node} when is_atom(Node) -> {ok, Node};
{error, Reason} -> {error, Reason};
Other -> {error, Other}
catch
exit:{timeout, _} -> {error, timeout};
exit:{noproc, _} -> {error, noproc}
end.