perf(emqx_alarm): use dirty Mnesia operations to activate an alarm

Alarms are stored in a local content shard and all 'activate' operations
are serialized as they are called by one process ('emqx_alarm' gen_server), so
using dirty operations gives performance gain without sacrificing consistency.

Fixes: EMQX-9529/#10357
This commit is contained in:
Serge Tupchii 2023-04-19 20:42:14 +03:00
parent b5eda9f0d1
commit b960d2ecb3
1 changed files with 8 additions and 14 deletions

View File

@ -57,7 +57,6 @@
%% Internal exports (RPC) %% Internal exports (RPC)
-export([ -export([
create_activate_alarm/3,
do_get_alarms/0 do_get_alarms/0
]). ]).
@ -218,17 +217,12 @@ init([]) ->
{ok, #{}, get_validity_period()}. {ok, #{}, get_validity_period()}.
handle_call({activate_alarm, Name, Details, Message}, _From, State) -> handle_call({activate_alarm, Name, Details, Message}, _From, State) ->
Res = mria:transaction( case create_activate_alarm(Name, Details, Message) of
mria:local_content_shard(), {ok, Alarm} ->
fun ?MODULE:create_activate_alarm/3,
[Name, Details, Message]
),
case Res of
{atomic, Alarm} ->
do_actions(activate, Alarm, emqx:get_config([alarm, actions])), do_actions(activate, Alarm, emqx:get_config([alarm, actions])),
{reply, ok, State, get_validity_period()}; {reply, ok, State, get_validity_period()};
{aborted, Reason} -> Err ->
{reply, Reason, State, get_validity_period()} {reply, Err, State, get_validity_period()}
end; end;
handle_call({deactivate_alarm, Name, Details, Message}, _From, State) -> handle_call({deactivate_alarm, Name, Details, Message}, _From, State) ->
case mnesia:dirty_read(?ACTIVATED_ALARM, Name) of case mnesia:dirty_read(?ACTIVATED_ALARM, Name) of
@ -283,9 +277,9 @@ get_validity_period() ->
emqx:get_config([alarm, validity_period]). emqx:get_config([alarm, validity_period]).
create_activate_alarm(Name, Details, Message) -> create_activate_alarm(Name, Details, Message) ->
case mnesia:read(?ACTIVATED_ALARM, Name) of case mnesia:dirty_read(?ACTIVATED_ALARM, Name) of
[#activated_alarm{name = Name}] -> [#activated_alarm{name = Name}] ->
mnesia:abort({error, already_existed}); {error, already_existed};
[] -> [] ->
Alarm = #activated_alarm{ Alarm = #activated_alarm{
name = Name, name = Name,
@ -293,8 +287,8 @@ create_activate_alarm(Name, Details, Message) ->
message = normalize_message(Name, iolist_to_binary(Message)), message = normalize_message(Name, iolist_to_binary(Message)),
activate_at = erlang:system_time(microsecond) activate_at = erlang:system_time(microsecond)
}, },
ok = mnesia:write(?ACTIVATED_ALARM, Alarm, write), ok = mria:dirty_write(?ACTIVATED_ALARM, Alarm),
Alarm {ok, Alarm}
end. end.
do_get_alarms() -> do_get_alarms() ->