feat(acl): Add possibility to remove all acl cache
This commit is contained in:
parent
cac0ee7f84
commit
c7b44caa1d
|
@ -27,6 +27,7 @@
|
||||||
, get_cache_max_size/0
|
, get_cache_max_size/0
|
||||||
, get_cache_ttl/0
|
, get_cache_ttl/0
|
||||||
, is_enabled/0
|
, is_enabled/0
|
||||||
|
, drain_cache/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% export for test
|
%% export for test
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
%% Wrappers for key and value
|
%% Wrappers for key and value
|
||||||
cache_k(PubSub, Topic)-> {PubSub, Topic}.
|
cache_k(PubSub, Topic)-> {PubSub, Topic}.
|
||||||
cache_v(AclResult)-> {AclResult, time_now()}.
|
cache_v(AclResult)-> {AclResult, time_now()}.
|
||||||
|
drain_k() -> {?MODULE, drain_timestamp}.
|
||||||
|
|
||||||
-spec(is_enabled() -> boolean()).
|
-spec(is_enabled() -> boolean()).
|
||||||
is_enabled() ->
|
is_enabled() ->
|
||||||
|
@ -86,10 +88,10 @@ get_acl_cache(PubSub, Topic) ->
|
||||||
put_acl_cache(PubSub, Topic, AclResult) ->
|
put_acl_cache(PubSub, Topic, AclResult) ->
|
||||||
MaxSize = get_cache_max_size(), true = (MaxSize =/= 0),
|
MaxSize = get_cache_max_size(), true = (MaxSize =/= 0),
|
||||||
Size = get_cache_size(),
|
Size = get_cache_size(),
|
||||||
if
|
case Size < MaxSize of
|
||||||
Size < MaxSize ->
|
true ->
|
||||||
add_acl(PubSub, Topic, AclResult);
|
add_acl(PubSub, Topic, AclResult);
|
||||||
Size =:= MaxSize ->
|
false ->
|
||||||
NewestK = get_newest_key(),
|
NewestK = get_newest_key(),
|
||||||
{_AclResult, CachedAt} = erlang:get(NewestK),
|
{_AclResult, CachedAt} = erlang:get(NewestK),
|
||||||
if_expired(CachedAt,
|
if_expired(CachedAt,
|
||||||
|
@ -145,6 +147,11 @@ foreach_acl_cache(Fun) ->
|
||||||
_ = map_acl_cache(Fun),
|
_ = map_acl_cache(Fun),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
%% All acl cache entries added before `drain_cache()` invocation will become expired
|
||||||
|
drain_cache() ->
|
||||||
|
_ = persistent_term:put(drain_k(), time_now()),
|
||||||
|
ok.
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Internal functions
|
%% Internal functions
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -185,11 +192,14 @@ incr_cache_size() ->
|
||||||
erlang:put(acl_cache_size, get_cache_size() + 1), ok.
|
erlang:put(acl_cache_size, get_cache_size() + 1), ok.
|
||||||
decr_cache_size() ->
|
decr_cache_size() ->
|
||||||
Size = get_cache_size(),
|
Size = get_cache_size(),
|
||||||
if Size > 1 ->
|
case Size > 1 of
|
||||||
|
true ->
|
||||||
erlang:put(acl_cache_size, Size-1);
|
erlang:put(acl_cache_size, Size-1);
|
||||||
Size =< 1 ->
|
false ->
|
||||||
erlang:put(acl_cache_size, 0)
|
erlang:put(acl_cache_size, 0)
|
||||||
end, ok.
|
end,
|
||||||
|
ok.
|
||||||
|
|
||||||
set_cache_size(N) ->
|
set_cache_size(N) ->
|
||||||
erlang:put(acl_cache_size, N), ok.
|
erlang:put(acl_cache_size, N), ok.
|
||||||
|
|
||||||
|
@ -239,8 +249,8 @@ time_now() -> erlang:system_time(millisecond).
|
||||||
if_expired(CachedAt, Fun) ->
|
if_expired(CachedAt, Fun) ->
|
||||||
TTL = get_cache_ttl(),
|
TTL = get_cache_ttl(),
|
||||||
Now = time_now(),
|
Now = time_now(),
|
||||||
if (CachedAt + TTL) =< Now ->
|
CurrentEvictTimestamp = persistent_term:get(drain_k(), 0),
|
||||||
Fun(true);
|
case CachedAt =< CurrentEvictTimestamp orelse (CachedAt + TTL) =< Now of
|
||||||
true ->
|
true -> Fun(true);
|
||||||
Fun(false)
|
false -> Fun(false)
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -55,6 +55,30 @@ t_clean_acl_cache(_) ->
|
||||||
?assertEqual(0, length(gen_server:call(ClientPid, list_acl_cache))),
|
?assertEqual(0, length(gen_server:call(ClientPid, list_acl_cache))),
|
||||||
emqtt:stop(Client).
|
emqtt:stop(Client).
|
||||||
|
|
||||||
|
|
||||||
|
t_drain_acl_cache(_) ->
|
||||||
|
{ok, Client} = emqtt:start_link([{clientid, <<"emqx_c">>}]),
|
||||||
|
{ok, _} = emqtt:connect(Client),
|
||||||
|
{ok, _, _} = emqtt:subscribe(Client, <<"t2">>, 0),
|
||||||
|
emqtt:publish(Client, <<"t1">>, <<"{\"x\":1}">>, 0),
|
||||||
|
ct:sleep(100),
|
||||||
|
ClientPid = case emqx_cm:lookup_channels(<<"emqx_c">>) of
|
||||||
|
[Pid] when is_pid(Pid) ->
|
||||||
|
Pid;
|
||||||
|
Pids when is_list(Pids) ->
|
||||||
|
lists:last(Pids);
|
||||||
|
_ -> {error, not_found}
|
||||||
|
end,
|
||||||
|
Caches = gen_server:call(ClientPid, list_acl_cache),
|
||||||
|
ct:log("acl caches: ~p", [Caches]),
|
||||||
|
?assert(length(Caches) > 0),
|
||||||
|
emqx_acl_cache:drain_cache(),
|
||||||
|
?assertEqual(0, length(gen_server:call(ClientPid, list_acl_cache))),
|
||||||
|
ct:sleep(100),
|
||||||
|
{ok, _, _} = emqtt:subscribe(Client, <<"t2">>, 0),
|
||||||
|
?assert(length(gen_server:call(ClientPid, list_acl_cache)) > 0),
|
||||||
|
emqtt:stop(Client).
|
||||||
|
|
||||||
% optimize??
|
% optimize??
|
||||||
t_reload_aclfile_and_cleanall(_Config) ->
|
t_reload_aclfile_and_cleanall(_Config) ->
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue