Merge pull request #13548 from JimMoen/feat-plugin-on-config-changed-callback

feat: call plugin's app module `on_config_changed/2` callback
This commit is contained in:
JimMoen 2024-07-31 16:40:48 +08:00 committed by GitHub
commit b1c8bc2421
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 2 deletions

View File

@ -356,13 +356,13 @@ get_config_bin(NameVsn) ->
%% RPC call from Management API or CLI.
%% The plugin config Json Map was valid by avro schema
%% Or: if no and plugin config ALWAYS be valid before calling this function.
put_config(NameVsn, ConfigJsonMap, AvroValue) when not is_binary(NameVsn) ->
put_config(NameVsn, ConfigJsonMap, AvroValue) when (not is_binary(NameVsn)) ->
put_config(bin(NameVsn), ConfigJsonMap, AvroValue);
put_config(NameVsn, ConfigJsonMap, _AvroValue) ->
HoconBin = hocon_pp:do(ConfigJsonMap, #{}),
ok = backup_and_write_hocon_bin(NameVsn, HoconBin),
%% TODO: callback in plugin's on_config_changed (config update by mgmt API)
%% TODO: callback in plugin's on_config_upgraded (config vsn upgrade v1 -> v2)
ok = maybe_call_on_config_changed(NameVsn, ConfigJsonMap),
ok = persistent_term:put(?PLUGIN_PERSIS_CONFIG_KEY(NameVsn), ConfigJsonMap),
ok.
@ -373,6 +373,43 @@ restart(NameVsn) ->
{error, Reason} -> {error, Reason}
end.
%% @doc Call plugin's callback on_config_changed/2
maybe_call_on_config_changed(NameVsn, NewConf) ->
FuncName = on_config_changed,
maybe
{ok, PluginAppModule} ?= app_module_name(NameVsn),
true ?= erlang:function_exported(PluginAppModule, FuncName, 2),
{ok, OldConf} = get_config(NameVsn),
try erlang:apply(PluginAppModule, FuncName, [OldConf, NewConf]) of
_ -> ok
catch
Class:CatchReason:Stacktrace ->
?SLOG(error, #{
msg => "failed_to_call_on_config_changed",
exception => Class,
reason => CatchReason,
stacktrace => Stacktrace
}),
ok
end
else
{error, Reason} ->
?SLOG(info, #{msg => "failed_to_call_on_config_changed", reason => Reason});
false ->
?SLOG(info, #{msg => "on_config_changed_callback_not_exported"});
_ ->
ok
end.
app_module_name(NameVsn) ->
case read_plugin_info(NameVsn, #{}) of
{ok, #{<<"name">> := Name} = _PluginInfo} ->
emqx_utils:safe_to_existing_atom(<<Name/binary, "_app">>);
{error, Reason} ->
?SLOG(error, Reason#{msg => "failed_to_read_plugin_info"}),
{error, Reason}
end.
%% @doc List all installed plugins.
%% Including the ones that are installed, but not enabled in config.
-spec list() -> [plugin_info()].

View File

@ -0,0 +1,6 @@
Optionally calls the `on_config_changed/2` callback function when the plugin configuration is updated via the REST API.
This callback function is assumed to be exported by the `<PluginName>_app` module.
i.e:
Plugin NameVsn: `my_plugin-1.0.0`
This callback function is assumed to be `my_plugin_app:on_config_changed/2`