HG-72: separate generic machine logic from business-specific error handling (#43)

This commit is contained in:
Evgeny Levenets 2016-10-27 20:07:06 +03:00 committed by GitHub
parent fe3f3ac110
commit 974a0cbb02
4 changed files with 51 additions and 28 deletions

View File

@ -145,10 +145,10 @@ process_callback(Tag, Callback, Context) ->
%%
get_history(_UserInfo, InvoiceID, Context) ->
map_error(hg_machine:get_history(?NS, InvoiceID, opts(Context))).
map_history_error(hg_machine:get_history(?NS, InvoiceID, opts(Context))).
get_history(_UserInfo, InvoiceID, AfterID, Limit, Context) ->
map_error(hg_machine:get_history(?NS, InvoiceID, AfterID, Limit, opts(Context))).
map_history_error(hg_machine:get_history(?NS, InvoiceID, AfterID, Limit, opts(Context))).
get_state(UserInfo, InvoiceID, Context0) ->
{{History, _LastID}, Context} = get_history(UserInfo, InvoiceID, Context0),
@ -180,14 +180,26 @@ start(ID, Args, Context) ->
call(ID, Args, Context) ->
map_error(hg_machine:call(?NS, {id, ID}, Args, opts(Context))).
map_error({{ok, Result}, Context}) ->
{Result, Context};
map_error({{ok, CallResult}, Context}) ->
case CallResult of
{ok, Result} ->
{Result, Context};
{exception, Reason} ->
throw({Reason, Context})
end;
map_error({{error, notfound}, Context}) ->
throw({#payproc_UserInvoiceNotFound{}, Context});
map_error({{error, Reason}, _Context}) ->
error(Reason).
map_start_error({ok, Context}) ->
map_history_error({{ok, Result}, Context}) ->
{Result, Context};
map_history_error({{error, notfound}, Context}) ->
throw({#payproc_PartyNotFound{}, Context});
map_history_error({{error, Reason}, _Context}) ->
error(Reason).
map_start_error({{ok, _}, Context}) ->
{ok, Context};
map_start_error({{error, Reason}, _Context}) ->
error(Reason).

View File

@ -84,26 +84,21 @@
%%
-spec start(ns(), id(), term(), opts()) ->
{ok | {error, exists}, woody_client:context()}.
{{ok, term()} | {error, exists | term()}, woody_client:context()}.
start(Ns, ID, Args, #{client_context := Context0}) ->
call_automaton('Start', [Ns, ID, wrap_args(Args)], Context0).
-spec call(ns(), ref(), term(), opts()) ->
{ok | {ok, term()} | {error, notfound | failed}, woody_client:context()} |
{{ok, term()} | {error, notfound | failed}, woody_client:context()} |
no_return().
call(Ns, Ref, Args, #{client_context := Context0}) ->
case call_automaton('Call', [Ns, Ref, wrap_args(Args)], Context0) of
{Response, Context} when is_binary(Response) ->
{{ok, Response}, Context} when is_binary(Response) ->
% should be specific to a processing interface already
case unmarshal_term(Response) of
{ok, _} = Ok ->
{Ok, Context};
{exception, Exception} ->
throw({Exception, Context})
end;
{Error = {error, _}, Context} ->
{{ok, unmarshal_term(Response)}, Context};
{{error, _} = Error, Context} ->
{Error, Context}
end.
@ -122,7 +117,7 @@ get_history(Ns, ID, AfterID, Limit, Opts) ->
get_history(Ns, ID, Range, #{client_context := Context0}) ->
LastID = #'HistoryRange'.'after',
case call_automaton('GetHistory', [Ns, {id, ID}, Range], Context0) of
{History, Context} when is_list(History) ->
{{ok, History}, Context} when is_list(History) ->
{{ok, unwrap_history(History, LastID)}, Context};
{Error, Context} ->
{Error, Context}
@ -134,7 +129,10 @@ call_automaton(Function, Args, Context0) ->
% TODO: hg_config module, aware of config entry semantics
Url = genlib_app:env(hellgate, automaton_service_url),
Service = {dmsl_state_processing_thrift, 'Automaton'},
try woody_client:call(Context0, {Service, Function, Args}, #{url => Url}) catch
try
{Result, Context1} = woody_client:call(Context0, {Service, Function, Args}, #{url => Url}),
{{ok, Result}, Context1}
catch
{{exception, #'MachineAlreadyExists'{}}, Context} ->
{{error, exists}, Context};
{{exception, #'MachineNotFound'{}}, Context} ->

View File

@ -147,14 +147,10 @@ handle_function('GetShopAccountSet', {UserInfo, PartyID, ShopID}, Context0, _Opt
get_history(PartyID, Context) ->
assert_nonempty_history(
map_error(hg_machine:get_history(?NS, PartyID, opts(Context)))
).
map_history_error(hg_machine:get_history(?NS, PartyID, opts(Context))).
get_history(PartyID, AfterID, Limit, Context) ->
assert_nonempty_history(
map_error(hg_machine:get_history(?NS, PartyID, AfterID, Limit, opts(Context)))
).
map_history_error(hg_machine:get_history(?NS, PartyID, AfterID, Limit, opts(Context))).
%% TODO remove this hack as soon as machinegun learns to tell the difference between
%% nonexsitent machine and empty history
@ -181,13 +177,25 @@ start(ID, Args, Context) ->
call(ID, Args, Context) ->
map_error(hg_machine:call(?NS, {id, ID}, Args, opts(Context))).
map_start_error({ok, Context}) ->
map_start_error({{ok, _}, Context}) ->
{ok, Context};
map_start_error({{error, exists}, Context}) ->
throw({#payproc_PartyExists{}, Context}).
map_error({{ok, Result}, Context}) ->
{Result, Context};
map_history_error({{ok, Result}, Context}) ->
assert_nonempty_history({Result, Context});
map_history_error({{error, notfound}, Context}) ->
throw({#payproc_PartyNotFound{}, Context});
map_history_error({{error, Reason}, _Context}) ->
error(Reason).
map_error({{ok, CallResult}, Context}) ->
case CallResult of
{ok, Result} ->
{Result, Context};
{exception, Reason} ->
throw({Reason, Context})
end;
map_error({{error, notfound}, Context}) ->
throw({#payproc_PartyNotFound{}, Context});
map_error({{error, Reason}, _Context}) ->

View File

@ -23,8 +23,13 @@
handle_function('ProcessCallback', {Tag, Callback}, Context, _) ->
map_error(hg_invoice:process_callback(Tag, {provider, Callback}, Context)).
map_error({{ok, Result}, Context}) ->
{Result, Context};
map_error({{ok, CallResult}, Context}) ->
case CallResult of
{ok, Result} ->
{Result, Context};
{exception, Reason} ->
throw({Reason, Context})
end;
map_error({{error, notfound}, Context}) ->
throw({#'InvalidRequest'{errors = [<<"notfound">>]}, Context});
map_error({{error, Reason}, _Context}) ->