Архивирование с быстрым подключением и серверный рендеринг для веб-клиента #15
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
-module(archive_manager).
|
||||
-behaviour(gen_server).
|
||||
|
||||
-export([start_link/0, get_archive_node/1]).
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
|
||||
|
||||
-define(TIMEOUT, 30000). % 30 секунд неактивности
|
||||
|
||||
start_link() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||
|
||||
get_archive_node(Day) ->
|
||||
gen_server:call(?MODULE, {get_node, Day}).
|
||||
|
||||
init([]) ->
|
||||
{ok, #{}}.
|
||||
|
||||
handle_call({get_node, Day}, _From, State) ->
|
||||
Node = list_to_atom("eventhub_archive_" ++ Day ++ "@" ++ host()),
|
||||
case maps:find(Node, State) of
|
||||
{ok, _Info} -> % переменная не используется, ок
|
||||
{reply, {ok, Node}, update_access(State, Node)};
|
||||
error ->
|
||||
case start_archive_node(Day) of
|
||||
{ok, Node} ->
|
||||
Ref = erlang:send_after(?TIMEOUT, self(), {release, Node}),
|
||||
NewState = State#{Node => #{timer => Ref, last_access => erlang:monotonic_time()}},
|
||||
{reply, {ok, Node}, NewState};
|
||||
{error, Reason} ->
|
||||
{reply, {error, Reason}, State}
|
||||
end
|
||||
end.
|
||||
|
||||
handle_cast(_, State) -> {noreply, State}.
|
||||
|
||||
handle_info({release, Node}, State) ->
|
||||
case maps:find(Node, State) of
|
||||
{ok, #{last_access := Last}} ->
|
||||
Now = erlang:monotonic_time(),
|
||||
if Now - Last >= (?TIMEOUT * 1000) ->
|
||||
stop_archive_node(Node),
|
||||
{noreply, maps:remove(Node, State)};
|
||||
true ->
|
||||
Ref = erlang:send_after(?TIMEOUT, self(), {release, Node}),
|
||||
{noreply, State#{Node => #{timer => Ref, last_access => Last}}}
|
||||
end;
|
||||
error ->
|
||||
{noreply, State}
|
||||
end;
|
||||
handle_info(_, State) -> {noreply, State}.
|
||||
|
||||
update_access(State, Node) ->
|
||||
Info = maps:get(Node, State),
|
||||
Ref = erlang:send_after(?TIMEOUT, self(), {release, 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
|
||||
{ok, _} ->
|
||||
rpc:call(Node, mnesia, start, []),
|
||||
{ok, Node};
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
stop_archive_node(Node) ->
|
||||
rpc:cast(Node, init, stop, []).
|
||||
|
||||
host() ->
|
||||
{ok, Name} = inet:gethostname(),
|
||||
Name.
|
||||
Reference in New Issue
Block a user