代码逻辑调整

This commit is contained in:
anlicheng 2026-04-27 14:53:35 +08:00
parent 87874135aa
commit a5280cde42
3 changed files with 130 additions and 117 deletions

View File

@ -11,6 +11,7 @@
%% API
-export([ensure_container_dir/2, ensure_container_dir/3, get_container_dir/2, get_config_file/1]).
-export([update_container_config/2]).
-spec ensure_container_dir(RootDir :: string(), ContainerName :: binary()) -> {ok, ServerRootDir :: string()}.
ensure_container_dir(RootDir, ContainerName) when is_list(RootDir), is_binary(ContainerName) ->
@ -49,6 +50,24 @@ get_container_dir(RootDir, ContainerName) when is_list(RootDir), is_binary(Conta
error
end.
-spec update_container_config(binary(), binary()) -> ok | {error, binary()}.
update_container_config(ContainerName, Config) when is_binary(ContainerName), is_binary(Config) ->
{ok, RootDir} = application:get_env(efka, root_dir),
case get_container_dir(RootDir, ContainerName) of
{ok, ContainerDir} ->
ConfigFile = get_config_file(ContainerDir),
case file:write_file(ConfigFile, Config, [write, binary]) of
ok ->
logger:warning("[efka_client] write config file: ~p success", [ConfigFile]),
ok;
{error, Reason} ->
logger:warning("[efka_client] write config file: ~p, get error: ~p", [ConfigFile, Reason]),
{error, <<"write config failed">>}
end;
error ->
{error, <<"error">>}
end.
-spec default_container_dir(RootDir :: string(), ContainerName :: binary()) -> string().
default_container_dir(RootDir, ContainerName) ->
normalize_container_dir(RootDir ++ "/" ++ binary_to_list(ContainerName)).

View File

@ -21,9 +21,6 @@
-export([init/1, handle_event/4, terminate/3, code_change/4, callback_mode/0]).
-define(SERVER, ?MODULE).
-define(CACHE_TAB, cache).
-define(MAX_CACHE_ITEMS, 5000000).
-define(MAX_CACHE_FILE_SIZE, 1073741824).
%% agent的状态 activated
-define(STATE_DISCONNECTED, disconnected).
@ -79,7 +76,7 @@ start_link() ->
-spec init(list()) -> {ok, atom(), #state{}}.
init([]) ->
case open_cache_table() of
case efka_client_cache:open() of
ok ->
erlang:start_timer(0, self(), create_transport),
{ok, ?STATE_DISCONNECTED, #state{socket = undefined}};
@ -91,7 +88,7 @@ init([]) ->
callback_mode() ->
handle_event_function.
%% , mnesia
%% , DETS
-spec handle_event(term(), term(), atom(), #state{}) -> term().
handle_event(cast, {metric_data, RouteKey, Metric}, StateName, State = #state{socket = Socket}) ->
Packet = term_to_binary({message, {data, #{route_key => RouteKey, metric => Metric}}}),
@ -100,7 +97,7 @@ handle_event(cast, {metric_data, RouteKey, Metric}, StateName, State = #state{so
ok = ssl:send(Socket, Packet),
{keep_state, State};
_ ->
{ok, DroppedCount} = cache_insert(Packet),
{ok, DroppedCount} = efka_client_cache:insert(Packet),
{keep_state, State#state{dropped_message_count = State#state.dropped_message_count + DroppedCount}}
end;
@ -148,10 +145,10 @@ handle_event(state_timeout, auth_timeout, ?STATE_AUTH, State = #state{socket = S
%%
handle_event(info, flush_cache, ?STATE_ACTIVATED, State = #state{socket = Socket}) ->
case cache_fetch_next() of
case efka_client_cache:fetch_next() of
{ok, {Id, Packet}} ->
ok = ssl:send(Socket, Packet),
ok = cache_delete(Id),
ok = efka_client_cache:delete(Id),
{keep_state, State, [{next_event, info, flush_cache}]};
error ->
{keep_state, State}
@ -207,7 +204,7 @@ handle_event(internal, {request, Ref, {container_request, #{action := remove, ta
{keep_state, State};
handle_event(internal, {request, Ref, {container_request, #{action := config, target := Target, config := Config}}},
?STATE_ACTIVATED, State = #state{socket = Socket}) ->
Reply = update_container_config(container_target(Target), iolist_to_binary(Config)),
Reply = docker_helper:update_container_config(container_target(Target), iolist_to_binary(Config)),
handle_container_response(Socket, Ref, Reply),
{keep_state, State};
handle_event(internal, {request, Ref, {container_request, Request}}, ?STATE_RESTRICTED, State = #state{socket = Socket}) ->
@ -266,7 +263,7 @@ handle_event(info, Info, _, State = #state{}) ->
-spec terminate(term(), atom(), #state{}) -> ok.
terminate(_Reason, _StateName, _State = #state{socket = Socket}) ->
disconnect(Socket),
close_cache_table(),
efka_client_cache:close(),
ok.
-spec code_change(term(), atom(), #state{}, term()) -> {ok, atom(), #state{}}.
@ -314,94 +311,6 @@ disconnect(Socket) ->
schedule_reconnect() ->
erlang:start_timer(5000, self(), create_transport).
-spec open_cache_table() -> ok | {error, term()}.
open_cache_table() ->
{ok, DetsDir} = application:get_env(efka, dets_dir),
File = DetsDir ++ "cache.dets",
case dets:open_file(?CACHE_TAB, [{file, File}, {type, bag}, {keypos, 1}]) of
{ok, ?CACHE_TAB} ->
ok;
{error, Reason} ->
{error, Reason}
end.
-spec close_cache_table() -> ok.
close_cache_table() ->
case dets:close(?CACHE_TAB) of
ok ->
ok;
{error, not_owner} ->
ok
end.
-spec cache_insert(binary()) -> {ok, non_neg_integer()} | {error, term()}.
cache_insert(Data) when is_binary(Data) ->
case dets:insert(?CACHE_TAB, {generate_cache_id(), Data}) of
ok ->
trim_cache_limits(0);
{error, Reason} ->
{error, Reason}
end.
-spec cache_fetch_next() -> error | {ok, {integer(), binary()}}.
cache_fetch_next() ->
case dets:first(?CACHE_TAB) of
'$end_of_table' ->
error;
Key ->
case dets:lookup(?CACHE_TAB, Key) of
[Entry | _] ->
{ok, Entry};
[] ->
cache_fetch_next()
end
end.
-spec cache_delete(integer()) -> ok | {error, term()}.
cache_delete(Id) when is_integer(Id) ->
dets:delete(?CACHE_TAB, Id).
-spec generate_cache_id() -> integer().
generate_cache_id() ->
erlang:unique_integer([monotonic, positive]).
-spec cache_over_limit() -> boolean().
cache_over_limit() ->
cache_item_count() > ?MAX_CACHE_ITEMS orelse cache_file_size() > ?MAX_CACHE_FILE_SIZE.
-spec cache_item_count() -> non_neg_integer().
cache_item_count() ->
dets:info(?CACHE_TAB, size).
-spec cache_file_size() -> non_neg_integer().
cache_file_size() ->
dets:info(?CACHE_TAB, file_size).
-spec trim_cache_limits(non_neg_integer()) -> {ok, non_neg_integer()} | {error, term()}.
trim_cache_limits(DroppedCount) ->
case cache_over_limit() of
true ->
case delete_oldest_cache_entry() of
ok ->
trim_cache_limits(DroppedCount + 1);
error ->
{ok, DroppedCount};
{error, Reason} ->
{error, Reason}
end;
false ->
{ok, DroppedCount}
end.
-spec delete_oldest_cache_entry() -> ok | error | {error, term()}.
delete_oldest_cache_entry() ->
case dets:first(?CACHE_TAB) of
'$end_of_table' ->
error;
Key ->
dets:delete(?CACHE_TAB, Key)
end.
-spec handle_container_response(ssl:sslsocket(), reference(), term()) -> ok.
handle_container_response(Socket, Ref, Reply) ->
Packet = term_to_binary({response, Ref, {container_response, Reply}}),
@ -434,21 +343,3 @@ to_bool(false) ->
false;
to_bool(0) ->
false.
-spec update_container_config(binary(), binary()) -> ok | {error, binary()}.
update_container_config(ContainerName, Config) when is_binary(ContainerName), is_binary(Config) ->
{ok, RootDir} = application:get_env(efka, root_dir),
case docker_helper:get_container_dir(RootDir, ContainerName) of
{ok, ContainerDir} ->
ConfigFile = docker_helper:get_config_file(ContainerDir),
case file:write_file(ConfigFile, Config, [write, binary]) of
ok ->
logger:warning("[efka_client] write config file: ~p success", [ConfigFile]),
ok;
{error, Reason} ->
logger:warning("[efka_client] write config file: ~p, get error: ~p", [ConfigFile, Reason]),
{error, <<"write config failed">>}
end;
error ->
{error, <<"error">>}
end.

View File

@ -0,0 +1,103 @@
%%%-------------------------------------------------------------------
%%% @author anlicheng
%%% @copyright (C) 2026, <COMPANY>
%%% @doc
%%% DETS backed outbound packet cache for efka_client.
%%% @end
%%%-------------------------------------------------------------------
-module(efka_client_cache).
-author("anlicheng").
-define(CACHE_TAB, cache).
-define(MAX_CACHE_ITEMS, 5000000).
-define(MAX_CACHE_FILE_SIZE, 1073741824).
-export([open/0, close/0, insert/1, fetch_next/0, delete/1]).
-spec open() -> ok | {error, term()}.
open() ->
{ok, DetsDir} = application:get_env(efka, dets_dir),
File = DetsDir ++ "cache.dets",
case dets:open_file(?CACHE_TAB, [{file, File}, {type, bag}, {keypos, 1}]) of
{ok, ?CACHE_TAB} ->
ok;
{error, Reason} ->
{error, Reason}
end.
-spec close() -> ok.
close() ->
case dets:close(?CACHE_TAB) of
ok ->
ok;
{error, not_owner} ->
ok
end.
-spec insert(binary()) -> {ok, non_neg_integer()} | {error, term()}.
insert(Data) when is_binary(Data) ->
case dets:insert(?CACHE_TAB, {generate_cache_id(), Data}) of
ok ->
trim_limits(0);
{error, Reason} ->
{error, Reason}
end.
-spec fetch_next() -> error | {ok, {integer(), binary()}}.
fetch_next() ->
case dets:first(?CACHE_TAB) of
'$end_of_table' ->
error;
Key ->
case dets:lookup(?CACHE_TAB, Key) of
[Entry | _] ->
{ok, Entry};
[] ->
fetch_next()
end
end.
-spec delete(integer()) -> ok | {error, term()}.
delete(Id) when is_integer(Id) ->
dets:delete(?CACHE_TAB, Id).
-spec generate_cache_id() -> integer().
generate_cache_id() ->
erlang:unique_integer([monotonic, positive]).
-spec over_limit() -> boolean().
over_limit() ->
item_count() > ?MAX_CACHE_ITEMS orelse file_size() > ?MAX_CACHE_FILE_SIZE.
-spec item_count() -> non_neg_integer().
item_count() ->
dets:info(?CACHE_TAB, size).
-spec file_size() -> non_neg_integer().
file_size() ->
dets:info(?CACHE_TAB, file_size).
-spec trim_limits(non_neg_integer()) -> {ok, non_neg_integer()} | {error, term()}.
trim_limits(DroppedCount) ->
case over_limit() of
true ->
case delete_oldest_entry() of
ok ->
trim_limits(DroppedCount + 1);
error ->
{ok, DroppedCount};
{error, Reason} ->
{error, Reason}
end;
false ->
{ok, DroppedCount}
end.
-spec delete_oldest_entry() -> ok | error | {error, term()}.
delete_oldest_entry() ->
case dets:first(?CACHE_TAB) of
'$end_of_table' ->
error;
Key ->
dets:delete(?CACHE_TAB, Key)
end.