Skip to content

Commit

Permalink
Implement an async endpoint for domain deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
NelsonVides committed Oct 16, 2022
1 parent 6e57aa3 commit 6454fe6
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 7 deletions.
8 changes: 8 additions & 0 deletions big_tests/tests/domain_rest_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
putt_domain_with_custom_body/2,
rest_select_domain/2,
rest_delete_domain/3,
request_delete_domain/3,
delete_custom/4,
patch_custom/4]).

Expand Down Expand Up @@ -73,6 +74,13 @@ rest_delete_domain(Config, Domain, HostType) ->
creds => make_creds(Config),
body => Params }).

request_delete_domain(Config, Domain, HostType) ->
Params = #{<<"host_type">> => HostType, <<"request">> => true},
rest_helper:make_request(#{ role => admin, method => <<"DELETE">>,
path => domain_path(Domain),
creds => make_creds(Config),
body => Params }).

delete_custom(Config, Role, Path, Body) ->
rest_helper:make_request(#{ role => Role, method => <<"DELETE">>,
path => Path, creds => make_creds(Config),
Expand Down
19 changes: 15 additions & 4 deletions src/domain/mongoose_domain_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
%% domain API
-export([insert_domain/2,
delete_domain/2,
request_delete_domain/2,
disable_domain/1,
enable_domain/1,
get_domain_host_type/1,
Expand All @@ -30,7 +31,8 @@
get_all_subdomains_for_domain/1]).

%% Helper for remove_domain
-export([remove_domain_wrapper/3]).
-export([remove_domain_wrapper/3,
do_delete_domain_in_progress/3]).

%% For testing
-export([get_all_dynamic/0]).
Expand Down Expand Up @@ -82,13 +84,20 @@ insert_domain(Domain, HostType) ->
%% Domain should be nameprepped using `jid:nameprep'.
-spec delete_domain(domain(), host_type()) -> delete_domain_return().
delete_domain(Domain, HostType) ->
do_delete_domain(Domain, HostType, sync).

-spec request_delete_domain(domain(), host_type()) -> delete_domain_return().
request_delete_domain(Domain, HostType) ->
do_delete_domain(Domain, HostType, async).

do_delete_domain(Domain, HostType, RequestType) ->
case check_domain(Domain, HostType) of
ok ->
Res0 = check_db(mongoose_domain_sql:set_domain_for_deletion(Domain, HostType)),
case Res0 of
ok ->
delete_domain_password(Domain),
do_delete_domain_in_progress(Domain, HostType);
do_delete_domain_in_progress(Domain, HostType, RequestType);
Other ->
Other
end;
Expand All @@ -98,8 +107,10 @@ delete_domain(Domain, HostType) ->

%% This is ran only in the context of `do_delete_domain',
%% so it can already skip some checks
-spec do_delete_domain_in_progress(domain(), host_type()) -> delete_domain_return().
do_delete_domain_in_progress(Domain, HostType) ->
-spec do_delete_domain_in_progress(domain(), host_type(), sync | async) -> delete_domain_return().
do_delete_domain_in_progress(Domain, HostType, async) ->
mongoose_domain_db_cleaner:request_delete_domain(Domain, HostType);
do_delete_domain_in_progress(Domain, HostType, sync) ->
case mongoose_hooks:remove_domain(HostType, Domain) of
#{failed := []} ->
check_db(mongoose_domain_sql:delete_domain(Domain, HostType));
Expand Down
18 changes: 17 additions & 1 deletion src/domain/mongoose_domain_db_cleaner.erl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
-include("mongoose_logger.hrl").

-export([start/1, stop/0]).
-export([start_link/1]).
-export([start_link/1, request_delete_domain/2]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
Expand Down Expand Up @@ -37,6 +37,10 @@ stop() ->
start_link(Opts) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, Opts, []).

-spec request_delete_domain(jid:lserver(), mongooseim:host_type()) -> ok.
request_delete_domain(Domain, HostType) ->
gen_server:cast(?MODULE, {delete_domain, Domain, HostType}).

%% ---------------------------------------------------------------------------
%% Server callbacks

Expand All @@ -51,6 +55,8 @@ handle_call(Request, From, State) ->
?UNEXPECTED_CALL(Request, From),
{reply, ok, State}.

handle_cast({delete_domain, Domain, HostType}, State) ->
{noreply, handle_delete_domain(Domain, HostType, State)};
handle_cast(Msg, State) ->
?UNEXPECTED_CAST(Msg),
{noreply, State}.
Expand Down Expand Up @@ -90,3 +96,13 @@ schedule_removal(State = #{max_age := MaxAge}) ->
handle_timeout(_TimerRef, {do_removal, LastEventId}, State) ->
mongoose_domain_sql:delete_events_older_than(LastEventId),
State.

handle_delete_domain(Domain, HostType, State) ->
try
mongoose_domain_api:do_delete_domain_in_progress(Domain, HostType, sync)
catch Class:Reason:Stacktrace ->
?LOG_ERROR(#{what => domain_deletion_failed,
domain => Domain, host_type => HostType,
class => Class, reason => Reason, stacktrace => Stacktrace})
end,
State.
2 changes: 2 additions & 0 deletions src/domain/mongoose_domain_sql.erl
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ set_status(Domain, Status) ->
case mongoose_domain_core:is_host_type_allowed(HostType) of
false ->
{error, unknown_host_type};
true when deleting =:= CurrentStatus ->
{error, domain_deleted};
true when Status =:= CurrentStatus ->
ok;
true ->
Expand Down
28 changes: 26 additions & 2 deletions src/mongoose_admin_api/mongoose_admin_api_domain.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
allowed_methods/2,
to_json/2,
from_json/2,
delete_resource/2]).
delete_resource/2,
delete_completed/2]).

-ignore_xref([to_json/2, from_json/2]).

Expand Down Expand Up @@ -69,6 +70,12 @@ from_json(Req, State) ->
delete_resource(Req, State) ->
try_handle_request(Req, State, fun handle_delete/2).

-spec delete_completed(req(), state()) -> {boolean(), req(), state()}.
delete_completed(Req, #{deletion := in_process} = State) ->
{false, Req, State};
delete_completed(Req, State) ->
{true, Req, State}.

%% Internal functions

handle_get(Req, State) ->
Expand Down Expand Up @@ -128,7 +135,24 @@ handle_delete(Req, State) ->
Bindings = cowboy_req:bindings(Req),
Domain = get_domain(Bindings),
Args = parse_body(Req),
HostType = get_host_type(Args),
handle_delete(Req, State, Domain, Args).

handle_delete(Req, State, Domain, #{host_type := HostType, request := true}) ->
async_delete(Req, State, Domain, HostType);
handle_delete(Req, State, Domain, #{host_type := HostType}) ->
sync_delete(Req, State, Domain, HostType);
handle_delete(_Req, _State, _Domain, #{}) ->
throw_error(bad_request, <<"'host_type' field is missing">>);
handle_delete(_Req, _State, _Domain, {error, empty}) ->
throw_error(bad_request, <<"body is empty">>);
handle_delete(_Req, _State, _Domain, {error, _}) ->
throw_error(bad_request, <<"failed to parse JSON">>).

async_delete(Req, State, Domain, HostType) ->
mongoose_domain_api:request_delete_domain(Domain, HostType),
{true, Req, State#{deletion => in_process}}.

sync_delete(Req, State, Domain, HostType) ->
case mongoose_domain_api:delete_domain(Domain, HostType) of
ok ->
{true, Req, State};
Expand Down

0 comments on commit 6454fe6

Please sign in to comment.