feat(relup): support providing 'Extra' parameter from appup.src

This commit is contained in:
Shawn 2022-03-02 10:48:10 +08:00
parent 41afbd2b13
commit 77e3c1d3ac
2 changed files with 43 additions and 31 deletions

View File

@ -49,20 +49,20 @@ inject_relup_instrs(Type, RUs) ->
%% The `{apply, emqx_relup, post_release_upgrade, []}` will be appended to the end of
%% the instruction lists.
append_emqx_relup_instrs(up, FromRelVsn, Instrs0) ->
Extra = #{}, %% we may need some extended args
filter_and_check_instrs(up, Instrs0) ++
{{UpExtra, _}, Instrs1} = filter_and_check_instrs(up, Instrs0),
Instrs1 ++
[ {load, {emqx_app, brutal_purge, soft_purge}}
, {load, {emqx_relup, brutal_purge, soft_purge}}
, {apply, {emqx_relup, post_release_upgrade, [FromRelVsn, Extra]}}
, {apply, {emqx_relup, post_release_upgrade, [FromRelVsn, UpExtra]}}
];
append_emqx_relup_instrs(down, ToRelVsn, Instrs0) ->
Extra = #{}, %% we may need some extended args
{{_, DnExtra}, Instrs1} = filter_and_check_instrs(down, Instrs0)
%% NOTE: When downgrading, we apply emqx_relup:post_release_downgrade/2 before reloading
%% or removing the emqx_relup module.
Instrs1 = filter_and_check_instrs(down, Instrs0) ++
Instrs1 ++
[ {load, {emqx_app, brutal_purge, soft_purge}}
, {apply, {emqx_relup, post_release_downgrade, [ToRelVsn, Extra]}}
, {apply, {emqx_relup, post_release_downgrade, [ToRelVsn, DnExtra]}}
],
%% emqx_relup does not exist before release "4.4.2"
LoadInsts =
@ -75,37 +75,49 @@ append_emqx_relup_instrs(down, ToRelVsn, Instrs0) ->
Instrs1 ++ LoadInsts.
filter_and_check_instrs(Type, Instrs) ->
case take_emqx_vsn_and_modules(Instrs) of
{EmqxAppVsn, EmqxMods, RemainInstrs} when EmqxAppVsn =/= not_found, EmqxMods =/= [] ->
case filter_fetch_emqx_mods_and_extra(Instrs) of
{_, _, [], _} ->
?ERROR("cannot find any 'load_object_code' instructions for app emqx", []),
error({instruction_not_found, load_object_code});
{UpExtra, DnExtra, EmqxMods, RemainInstrs} ->
assert_mandatory_modules(Type, EmqxMods),
[{load_object_code, {emqx, EmqxAppVsn, EmqxMods}} | RemainInstrs];
{_, _, _} ->
?ERROR("cannot found 'load_module' instructions for app emqx", []),
error({instruction_not_found, load_object_code})
{{UpExtra, DnExtra}, RemainInstrs}
end.
take_emqx_vsn_and_modules(Instrs) ->
lists:foldl(fun
({load_object_code, {emqx, AppVsn, Mods}}, {_EmqxAppVsn, EmqxMods, RemainInstrs}) ->
{AppVsn, EmqxMods ++ Mods, RemainInstrs};
({load, {Mod, _, _}}, {EmqxAppVsn, EmqxMods, RemainInstrs})
filter_fetch_emqx_mods_and_extra(Instrs) ->
lists:foldl(fun do_filter_and_get/2, {UpExtra, DnExtra, [], []}, Instrs).
%% collect modules for emqx app
do_filter_and_get({load_object_code, {emqx, _AppVsn, Mods}} = Instr,
{UpExtra, DnExtra, EmqxMods, RemainInstrs}) ->
{UpExtra, DnExtra, EmqxMods ++ Mods, RemainInstrs ++ [Instr]};
%% remove 'load' instrs
do_filter_and_get({load, {Mod, _, _}}, {UpExtra, DnExtra, EmqxMods, RemainInstrs})
when Mod =:= emqx_relup; Mod =:= emqx_app ->
{EmqxAppVsn, EmqxMods, RemainInstrs};
({remove, {emqx_relup, _, _}}, {EmqxAppVsn, EmqxMods, RemainInstrs}) ->
{EmqxAppVsn, EmqxMods, RemainInstrs};
({apply, {emqx_relup, _, _}}, {EmqxAppVsn, EmqxMods, RemainInstrs}) ->
{EmqxAppVsn, EmqxMods, RemainInstrs};
(Instr, {EmqxAppVsn, EmqxMods, RemainInstrs}) ->
{EmqxAppVsn, EmqxMods, RemainInstrs ++ [Instr]}
end, {not_found, [], []}, Instrs).
{UpExtra, DnExtra, EmqxMods, RemainInstrs};
%% remove 'remove' instrs
do_filter_and_get({remove, {emqx_relup, _, _}}, {UpExtra, DnExtra, EmqxMods, RemainInstrs}) ->
{UpExtra, DnExtra, EmqxMods, RemainInstrs};
%% remove 'apply' instrs for upgrade, and collect the 'Extra' parameter
do_filter_and_get({apply, {emqx_relup, post_release_upgrade, [_, UpExtra0]}},
{_, DnExtra, EmqxMods, RemainInstrs}) ->
{UpExtra0, DnExtra, EmqxMods, RemainInstrs};
%% remove 'apply' instrs for downgrade, and collect the 'Extra' parameter
do_filter_and_get({apply, {emqx_relup, post_release_downgrade, [_, DnExtra0]}},
{UpExtra, _, EmqxMods, RemainInstrs}) ->
{UpExtra, DnExtra0, EmqxMods, RemainInstrs};
%% keep all other instrs unchanged
do_filter_and_get(Instr, {UpExtra, DnExtra, EmqxMods, RemainInstrs}) ->
{UpExtra, DnExtra, EmqxMods, RemainInstrs ++ [Instr]}.
assert_mandatory_modules(up, Mods) ->
assert(lists:member(emqx_relup, Mods) andalso lists:member(emqx_app, Mods),
"cannot found 'load_module' instructions for emqx_app and emqx_rel: ~p", [Mods]);
"cannot find any 'load_object_code' instructions for emqx_app and emqx_rel: ~p", [Mods]);
assert_mandatory_modules(down, Mods) ->
assert(lists:member(emqx_app, Mods),
"cannot found 'load_module' instructions for emqx_app", []).
"cannot find any 'load_object_code' instructions for emqx_app", []).
assert(true, _, _) ->
ok;

View File

@ -17,7 +17,7 @@
-module(emqx_relup).
%% NOTE: DO NOT remove this `-include`.
%% We use this to forece this module to upgraded every release.
%% We use this to force this module to be upgraded every release.
-include("emqx_release.hrl").
-export([ post_release_upgrade/2
@ -27,13 +27,13 @@
-define(INFO(FORMAT), io:format("[emqx_relup] " ++ FORMAT ++ "~n")).
-define(INFO(FORMAT, ARGS), io:format("[emqx_relup] " ++ FORMAT ++ "~n", ARGS)).
%% what to do after upgraded from a old release vsn.
%% What to do after upgraded from an old release vsn.
post_release_upgrade(FromRelVsn, _) ->
{_, CurrRelVsn} = ?EMQX_RELEASE,
?INFO("emqx has been upgraded to from ~s to ~s!", [FromRelVsn, CurrRelVsn]),
reload_components().
%% what to do after downgraded to a old release vsn.
%% What to do after downgraded to an old release vsn.
post_release_downgrade(ToRelVsn, _) ->
{_, CurrRelVsn} = ?EMQX_RELEASE,
?INFO("emqx has been downgraded to from ~s to ~s!", [CurrRelVsn, ToRelVsn]),