Skip to content

Commit

Permalink
HELP-45446: [master] move when termination handlers are running to cf…
Browse files Browse the repository at this point in the history
…_exe termination (2600hz#5984)

* move when termination handlers are running to cf_exe termination
  • Loading branch information
icehess authored and lazedo committed Sep 11, 2019
1 parent 6d2bebe commit 13279cb
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 56 deletions.
88 changes: 53 additions & 35 deletions applications/callflow/src/cf_exe.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
-export([hard_stop/1]).
-export([transfer/1]).
-export([control_usurped/1]).
-export([channel_destroyed/1]).
-export([channel_destroyed/1, channel_destroyed/2]).
-export([is_channel_destroyed/1]).
-export([stop_on_destroy/1
,continue_on_destroy/1
Expand Down Expand Up @@ -73,6 +73,7 @@
,flows = [] :: kz_json:objects()
,cf_module_pid :: kz_term:api_pid_ref()
,cf_module_old_pid :: kz_term:api_pid_ref()
,hangup_info = 'undefined' :: kz_term:api_object()
,status = 'init' :: callfow_status()
,amqp_worker :: pid()
,amqp_queue :: kz_term:ne_binary()
Expand Down Expand Up @@ -211,11 +212,15 @@ control_usurped(Call) ->
control_usurped(Srv).

-spec channel_destroyed(kapps_call:call() | pid()) -> 'ok'.
channel_destroyed(Srv) when is_pid(Srv) ->
gen_server:cast(Srv, 'channel_destroyed');
channel_destroyed(Call) ->
channel_destroyed(Srv) ->
channel_destroyed(Srv, 'undefined').

-spec channel_destroyed(kapps_call:call() | pid(), kz_term:api_object()) -> 'ok'.
channel_destroyed(Srv, JObj) when is_pid(Srv) ->
gen_server:cast(Srv, {'channel_destroyed', JObj});
channel_destroyed(Call, JObj) ->
Srv = cf_exe_pid(Call),
channel_destroyed(Srv).
channel_destroyed(Srv, JObj).

-spec stop_on_destroy(kapps_call:call() | pid()) -> 'ok'.
stop_on_destroy(Srv) when is_pid(Srv) ->
Expand Down Expand Up @@ -442,16 +447,12 @@ handle_cast({'continue', _}, #state{stop_on_destroy='true'
lager:info("channel no longer active, not continuing"),
hard_stop(self()),
{'noreply', State};
handle_cast({'continue', Key}, #state{flow=Flow
,call=Call
,termination_handlers=Handlers
}=State) ->
handle_cast({'continue', Key}, #state{flow=Flow}=State) ->
lager:info("continuing to child '~s'", [Key]),

case kz_json:get_value([<<"children">>, Key], Flow) of
'undefined' when Key =:= ?DEFAULT_CHILD_KEY ->
lager:info("wildcard child does not exist, we are lost...hanging up"),
maybe_run_destroy_handlers(Call, kz_json:new(), Handlers),
lager:info("wildcard child does not exist, we are lost... hanging up"),
stop(self()),
{'noreply', State};
'undefined' ->
Expand Down Expand Up @@ -485,14 +486,14 @@ handle_cast('transfer', State) ->
{'stop', {'shutdown', 'transfer'}, State};
handle_cast('control_usurped', State) ->
{'stop', {'shutdown', 'control_usurped'}, State};
handle_cast('channel_destroyed', #state{stop_on_destroy='true'
,cf_module_pid='undefined'
}=State) ->
handle_cast({'channel_destroyed', JObj}, #state{stop_on_destroy='true'
,cf_module_pid='undefined'
}=State) ->
lager:info("recv channel destroyed, going down"),
{'stop', 'normal', State};
handle_cast('channel_destroyed', State) ->
{'stop', 'normal', State#state{hangup_info=JObj}};
handle_cast({'channel_destroyed', JObj}, State) ->
lager:info("recv channel destroyed, noting but staying up"),
{'noreply', State#state{destroyed='true'}};
{'noreply', State#state{destroyed='true', hangup_info=JObj}};
handle_cast('stop_on_destroy', State) ->
{'noreply', State#state{stop_on_destroy='true'}};
handle_cast('continue_on_destroy', State) ->
Expand Down Expand Up @@ -630,7 +631,6 @@ handle_info(_Msg, State) ->
handle_event(JObj, #state{cf_module_pid=PidRef
,call=Call
,self=Self
,termination_handlers=DestoryHandlers
}) ->
CallId = kapps_call:call_id_direct(Call),
Others = kapps_call:kvs_fetch('cf_event_pids', [], Call),
Expand All @@ -641,9 +641,9 @@ handle_event(JObj, #state{cf_module_pid=PidRef

case {kz_util:get_event_type(JObj), kz_call_event:call_id(JObj)} of
{{<<"call_event">>, <<"CHANNEL_DESTROY">>}, CallId} ->
handle_channel_destroyed(Self, Notify, JObj, Call, DestoryHandlers);
handle_channel_destroyed(Self, Notify, JObj);
{{<<"call_event">>, <<"CHANNEL_DISCONNECTED">>}, CallId} ->
handle_channel_destroyed(Self, Notify, JObj, Call, DestoryHandlers);
handle_channel_destroyed(Self, Notify, JObj);
{{<<"call_event">>, <<"CHANNEL_TRANSFEREE">>}, _} ->
handle_channel_transfer(Call, JObj);
{{<<"call_event">>, <<"CHANNEL_REPLACED">>}, _} ->
Expand Down Expand Up @@ -696,18 +696,24 @@ terminate({'shutdown', 'control_usurped'}, #state{amqp_worker=AMQPWorker
terminate(_Reason, #state{call=Call
,cf_module_pid='undefined'
,amqp_worker=AMQPWorker
}) ->
hangup_call(Call, 'undefined', AMQPWorker),
,hangup_info=HangupInfo
,termination_handlers=DestroyHandlers
}=State) ->
lager:info("callflow execution has been stopped: ~p", [_Reason]),
maybe_hangup_call(State),
run_destroy_handlers(Call, HangupInfo, DestroyHandlers),
gen_listener:rm_binding(AMQPWorker, 'call', [{'callid', kapps_call:call_id_direct(Call)}]),
kz_amqp_worker:checkin_worker(AMQPWorker);
terminate(_Reason, #state{call=Call
,cf_module_pid={Pid, _}
,amqp_worker=AMQPWorker
}) ->
exit(Pid, 'kill'),
hangup_call(Call, 'undefined', AMQPWorker),
,hangup_info=HangupInfo
,termination_handlers=DestroyHandlers
}=State) ->
lager:info("callflow execution has been stopped: ~p", [_Reason]),
exit(Pid, 'kill'),
maybe_hangup_call(State),
run_destroy_handlers(Call, HangupInfo, DestroyHandlers),
gen_listener:rm_binding(AMQPWorker, 'call', [{'callid', kapps_call:call_id_direct(Call)}]),
kz_amqp_worker:checkin_worker(AMQPWorker).

Expand Down Expand Up @@ -875,11 +881,15 @@ log_call_information(Call) ->
end,
lager:info("authorizing id ~s", [kapps_call:authorizing_id(Call)]).

-spec handle_channel_destroyed(pid(), kz_term:pids(), kz_json:object(), kapps_call:call(), termination_handlers()) -> 'ok'.
handle_channel_destroyed(Self, Notify, JObj, Call, DestoryHandlers) ->
channel_destroyed(Self),
relay_message(Notify, JObj),
maybe_run_destroy_handlers(Call, JObj, DestoryHandlers).
-spec handle_channel_destroyed(pid(), kz_term:pids(), kz_json:object()) -> 'ok'.
handle_channel_destroyed(Self, Notify, JObj) ->
{Cause, Code} = kapps_util:get_call_termination_reason(JObj),
Prop = [{<<"Disposition">>, kz_call_event:disposition(JObj)}
,{<<"Hangup-Cause">>, Cause}
,{<<"Hangup-Code">>, Code}
],
channel_destroyed(Self, kz_json:from_list(Prop)),
relay_message(Notify, JObj).

-spec handle_channel_transfer(kapps_call:call(), kz_json:object()) -> 'ok'.
handle_channel_transfer(Call, JObj) ->
Expand Down Expand Up @@ -930,10 +940,10 @@ handle_usurp(Self, Call, JObj) ->

-spec handle_error(kz_term:ne_binary(), kz_term:pids(), kz_json:object()) -> 'ok'.
handle_error(CallId, Notify, JObj) ->
case kz_json:get_value([<<"Request">>, <<"Call-ID">>], JObj) of
CallId -> relay_message(Notify, JObj);
case kz_json:get_ne_binary_value(<<"Call-ID">>, JObj, kz_json:get_ne_binary_value([<<"Request">>, <<"Call-ID">>], JObj)) of
CallId -> relay_message(Notify, JObj);
'undefined' -> relay_message(Notify, JObj);
_Else -> 'ok'
_Else -> 'ok'
end.

-spec relay_message(kz_term:pids(), kz_json:object()) -> 'ok'.
Expand All @@ -944,15 +954,23 @@ relay_message(Notify, Message) ->
],
'ok'.

-spec maybe_run_destroy_handlers(kapps_call:call(), kz_json:object(), termination_handlers()) -> 'ok'.
maybe_run_destroy_handlers(Call, JObj, Handlers) ->
-spec run_destroy_handlers(kapps_call:call(), kz_json:object(), termination_handlers()) -> 'ok'.
run_destroy_handlers(Call, JObj, Handlers) ->
_ = [erlang:apply(M, F, [Call, JObj | Args]) || {M, F, Args} <- Handlers],
'ok'.

-spec get_pid({pid(), reference()} | 'undefined') -> kz_term:api_pid().
get_pid({Pid, _}) when is_pid(Pid) -> Pid;
get_pid(_) -> 'undefined'.

-spec maybe_hangup_call(state()) -> 'ok'.
maybe_hangup_call(#state{amqp_worker=AMQPWorker
,call=Call
,hangup_info='undefined'
}) ->
hangup_call(Call, 'undefined', AMQPWorker);
maybe_hangup_call(#state{}) -> 'ok'.

-spec hangup_call(kapps_call:call(), kz_term:api_ne_binary(), pid()) -> 'ok'.
hangup_call(Call, Cause, AMQPWorker) ->
Cmd = [{<<"Event-Name">>, <<"command">>}
Expand Down
21 changes: 12 additions & 9 deletions applications/callflow/src/module/cf_missed_call_alert.erl
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,18 @@ maybe_add_handle(_Data, Call, _Wat) ->
%% or voicemail message left flags are set
%% @end
%%------------------------------------------------------------------------------
-spec handle_termination(kapps_call:call(), kz_json:object(), kz_json:object()) -> kapps_call:call().
handle_termination(Call, Notify, Data) ->
case should_handle_termination(Call)
andalso find_email_addresses(Call, kz_json:get_value(<<"recipients">>, Data, []))
of
'false' -> Call;
[] -> send_missed_alert(Call, Notify, 'undefined');
Emails -> send_missed_alert(Call, Notify, Emails)
-spec handle_termination(kapps_call:call(), kz_json:object(), kz_json:object()) -> 'ok'.
handle_termination(Call, JObj, Data) ->
handle_termination(Call, JObj, Data, should_handle_termination(Call)).

-spec handle_termination(kapps_call:call(), kz_json:object(), kz_json:object(), boolean()) -> 'ok'.
handle_termination(_, _, _, 'false') ->
lager:debug("doing nothing, call has been bridged or a message was left");
handle_termination(Call, JObj, Data, 'true') ->
lager:debug("call went unanswered and left no voicemail message"),
case find_email_addresses(Call, kz_json:get_value(<<"recipients">>, Data, [])) of
[] -> send_missed_alert(Call, JObj, 'undefined');
Emails -> send_missed_alert(Call, JObj, Emails)
end.

%%%=============================================================================
Expand Down Expand Up @@ -122,7 +126,6 @@ send_missed_alert(Call, Notify, Emails) ->
-spec find_email_addresses(kapps_call:call(), kz_json:objects()) -> kz_term:ne_binaries().
find_email_addresses(Call, Recipients) ->
AccountDb = kz_util:format_account_db(kapps_call:account_id(Call)),
lager:debug("call went unanswered and left no voicemail message, finding configured email addresses"),
lists:flatten(
[Emails
|| JObj <- Recipients,
Expand Down
11 changes: 3 additions & 8 deletions core/kazoo_apps/src/kapps_util.erl
Original file line number Diff line number Diff line change
Expand Up @@ -499,14 +499,9 @@ cache(Key, AccountDbs) ->
%%------------------------------------------------------------------------------
-spec get_call_termination_reason(kz_json:object()) -> {kz_term:ne_binary(), kz_term:ne_binary()}.
get_call_termination_reason(JObj) ->
Cause = case kz_json:get_ne_value(<<"Application-Response">>, JObj) of
'undefined' ->
kz_json:get_ne_value(<<"Hangup-Cause">>, JObj, <<"UNSPECIFIED">>);
Response ->
Response
end,
Code = kz_json:get_value(<<"Hangup-Code">>, JObj, <<"sip:600">>),
{Cause, Code}.
{kz_call_event:application_response(JObj, kz_call_event:hangup_cause(JObj, <<"UNSPECIFIED">>))
,kz_call_event:hangup_code(JObj, <<"sip:600">>)
}.

%%------------------------------------------------------------------------------
%% @doc Reads all view files from given `Folder' in the given `App'.
Expand Down
16 changes: 12 additions & 4 deletions core/kazoo_documents/src/kz_call_event.erl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
,application_data/1
,application_event/1
,application_name/1
,application_response/1
,application_response/1, application_response/2
,application_uuid/1
,authorizing_id/1
,authorizing_type/1
Expand All @@ -36,7 +36,7 @@
,error_message/1, error_message/2
,event_name/1
,hangup_cause/1, hangup_cause/2
,hangup_code/1
,hangup_code/1, hangup_code/2
,is_authorized/1
,is_call_forwarded/1, is_call_forwarded/2
,other_leg_call_id/1
Expand Down Expand Up @@ -180,7 +180,11 @@ hangup_cause(JObj, Default) ->

-spec hangup_code(doc()) -> kz_term:api_ne_binary().
hangup_code(JObj) ->
kz_json:get_ne_binary_value(<<"Hangup-Code">>, JObj).
hangup_code(JObj, 'undefined').

-spec hangup_code(doc(), Default) -> kz_term:ne_binary() | Default.
hangup_code(JObj, Default) ->
kz_json:get_ne_binary_value(<<"Hangup-Code">>, JObj, Default).

-spec disposition(doc()) -> kz_term:api_ne_binary().
disposition(JObj) ->
Expand All @@ -204,7 +208,11 @@ application_uuid(JObj) ->

-spec application_response(doc()) -> kz_term:api_ne_binary().
application_response(JObj) ->
kz_json:get_ne_binary_value(<<"Application-Response">>, JObj).
application_response(JObj, 'undefined').

-spec application_response(doc(), Default) -> kz_term:ne_binary() | Default.
application_response(JObj, Default) ->
kz_json:get_ne_binary_value(<<"Application-Response">>, JObj, Default).

-spec response_message(doc()) -> kz_term:api_ne_binary().
response_message(JObj) ->
Expand Down

0 comments on commit 13279cb

Please sign in to comment.