DC-11: bumped to transient woody (#23)

This commit is contained in:
Evgeny Levenets 2016-12-29 15:09:33 +03:00 committed by GitHub
parent 3e59aea58d
commit 54b967b351
8 changed files with 120 additions and 166 deletions

View File

@ -1,4 +1,4 @@
[{<<"certifi">>,{pkg,<<"certifi">>,<<"0.4.0">>},2},
[{<<"certifi">>,{pkg,<<"certifi">>,<<"0.7.0">>},2},
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"1.0.4">>},1},
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"1.0.2">>},2},
{<<"dmsl">>,
@ -11,14 +11,14 @@
0},
{<<"dmt_client">>,
{git,"git@github.com:rbkmoney/dmt_client.git",
{ref,"22155b2dadd35298b4a1dbfb16b509b944eaed87"}},
{ref,"8b2982e409b39076d41320dd08155eecf406cc1a"}},
0},
{<<"genlib">>,
{git,"https://github.com/rbkmoney/genlib.git",
{ref,"ea85932ecf19fe39c87237fe5916ba1f65fc0bd6"}},
0},
{<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.7">>},1},
{<<"hackney">>,{pkg,<<"hackney">>,<<"1.5.7">>},1},
{<<"hackney">>,{pkg,<<"hackney">>,<<"1.6.2">>},1},
{<<"idna">>,{pkg,<<"idna">>,<<"1.2.0">>},2},
{<<"jsx">>,{pkg,<<"jsx">>,<<"2.8.0">>},1},
{<<"lager">>,{pkg,<<"lager">>,<<"3.0.2">>},0},
@ -34,12 +34,12 @@
{git,"https://github.com/rbkmoney/snowflake.git",
{ref,"36b978a3ad711c9d9349b799a24c5499a95ae29a"}},
1},
{<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.0">>},2},
{<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.1">>},2},
{<<"thrift">>,
{git,"https://github.com/rbkmoney/thrift_erlang.git",
{ref,"f132805904307376831fc2dd3780148b4b91aae2"}},
{ref,"aca7fca9f1a7161a1324bf5b92f8402c90d0519e"}},
1},
{<<"woody">>,
{git,"git@github.com:rbkmoney/woody_erlang.git",
{ref,"49f47a8b3d0429269d389e2207b94879b9088380"}},
{ref,"e1782b323ba324157f144ae75f1141e17dd5d027"}},
0}].

View File

@ -20,34 +20,31 @@
-type context() :: woody_client:context().
-spec checkout(dmt:ref(), context()) ->
{dmt:snapshot() | {error, version_not_found}, context()}.
-spec checkout(dmt:ref(), context()) -> dmt:snapshot() | {error, version_not_found}.
checkout(Reference, Context) ->
try
{dmt_cache:checkout(Reference), Context}
dmt_cache:checkout(Reference)
catch
version_not_found ->
dmt_api_context:map(
try_get_snapshot(Reference, Context),
fun
(Snapshot = #'Snapshot'{}) -> dmt_cache:cache_snapshot(Snapshot);
(Error = {error, _}) -> Error
end
)
case try_get_snapshot(Reference, Context) of
Snapshot = #'Snapshot'{} ->
dmt_cache:cache_snapshot(Snapshot);
{error, version_not_found} ->
{error, version_not_found}
end
end.
-spec try_get_snapshot(dmt:ref(), context()) ->
{dmt:snapshot() | {error, version_not_found}, context()}.
-spec try_get_snapshot(dmt:ref(), context()) -> dmt:snapshot() | {error, version_not_found}.
try_get_snapshot(Reference, Context) ->
{History, Context1} = dmt_api_mg:get_history(undefined, reference_to_limit(Reference), Context),
{case {Reference, dmt_history:head(History)} of
History = dmt_api_mg:get_history(undefined, reference_to_limit(Reference), Context),
case {Reference, dmt_history:head(History)} of
{{head, #'Head'{}}, Snapshot} ->
Snapshot;
{{version, V}, Snapshot = #'Snapshot'{version = V}} ->
Snapshot;
{{version, V1}, #'Snapshot'{version = V2}} when V1 > V2 ->
{error, version_not_found}
end, Context1}.
end.
-spec reference_to_limit(dmt:ref()) -> pos_integer() | undefined.
reference_to_limit({head, #'Head'{}}) ->
@ -56,15 +53,15 @@ reference_to_limit({version, Version}) ->
Version.
-spec checkout_object(dmt:ref(), dmt:object_ref(), context()) ->
{dmsl_domain_config_thrift:'VersionedObject'() | {error, version_not_found | object_not_found}, context()}.
dmsl_domain_config_thrift:'VersionedObject'() | {error, version_not_found | object_not_found}.
checkout_object(Reference, ObjectReference, Context) ->
dmt_api_context:map(
checkout(Reference, Context),
fun
(Snapshot = #'Snapshot'{}) -> try_get_object(ObjectReference, Snapshot);
(Error = {error, _}) -> Error
end
).
Snapshot = checkout(Reference, Context),
case Snapshot of
#'Snapshot'{} ->
try_get_object(ObjectReference, Snapshot);
{error, _} ->
Snapshot
end.
try_get_object(ObjectReference, #'Snapshot'{version = Version, domain = Domain}) ->
case dmt_domain:get_object(ObjectReference, Domain) of
@ -74,24 +71,21 @@ try_get_object(ObjectReference, #'Snapshot'{version = Version, domain = Domain})
{error, object_not_found}
end.
-spec pull(dmt:version(), context()) ->
{dmt:history() | {error, version_not_found}, context()}.
-spec pull(dmt:version(), context()) -> dmt:history() | {error, version_not_found}.
pull(Version, Context) ->
dmt_api_mg:get_history(Version, undefined, Context).
-spec commit(dmt:version(), dmt:commit(), context()) ->
{dmt:version() | {error, version_not_found | operation_conflict}, context()}.
dmt:version() | {error, version_not_found | operation_conflict}.
commit(Version, Commit, Context) ->
dmt_api_context:map(
dmt_api_mg:commit(Version, Commit, Context),
fun
(Snapshot = #'Snapshot'{version = VersionNext}) ->
_ = dmt_cache:cache_snapshot(Snapshot),
VersionNext;
(Error = {error, _}) ->
Error
end
).
Snapshot = dmt_api_mg:commit(Version, Commit, Context),
case Snapshot of
#'Snapshot'{version = VersionNext} ->
_ = dmt_cache:cache_snapshot(Snapshot),
VersionNext;
{error, _} ->
Snapshot
end.
-spec apply_commit(dmt:version(), dmt:commit(), dmt:history()) ->
{ok, dmt:snapshot()} | {error, term()}.
@ -132,8 +126,8 @@ init([]) ->
#{
ip => IP,
port => genlib_app:env(?MODULE, port, 8022),
net_opts => [],
event_handler => dmt_api_woody_event_handler,
net_opts => #{},
event_handler => woody_event_handler_default,
handlers => [
get_handler_spec(repository),
get_handler_spec(repository_client),
@ -144,25 +138,22 @@ init([]) ->
Children = [API],
{ok, {#{strategy => one_for_one, intensity => 10, period => 60}, Children}}.
-spec get_handler_spec(Which) -> {Path, {woody_t:service(), module(), term()}} when
-spec get_handler_spec(Which) -> {Path, {woody:service(), module()}} when
Which :: repository | repository_client | state_processor,
Path :: iodata().
get_handler_spec(repository) ->
{"/v1/domain/repository", {
{dmsl_domain_config_thrift, 'Repository'},
dmt_api_repository_handler,
[]
dmt_api_repository_handler
}};
get_handler_spec(repository_client) ->
{"/v1/domain/repository_client", {
{dmsl_domain_config_thrift, 'RepositoryClient'},
dmt_api_repository_client_handler,
[]
dmt_api_repository_client_handler
}};
get_handler_spec(state_processor) ->
{"/v1/stateproc", {
{dmsl_state_processing_thrift, 'Processor'},
dmt_api_state_processor,
[]
dmt_api_state_processor
}}.

View File

@ -1,20 +0,0 @@
-module(dmt_api_context).
-type context() :: woody_client:context().
-export([new/0]).
-export([map/2]).
-spec new() -> woody_client:context().
new() ->
ReqID = woody_client:make_unique_int(),
woody_client:new_context(genlib:to_binary(ReqID), dmt_api_woody_event_handler).
-spec map({T1, context()}, fun((T1) -> T2)) ->
{T2, woody_client:context()} when
T1 :: term(),
T2 :: term().
map({T, Context}, Fun) ->
{Fun(T), Context}.

View File

@ -26,24 +26,24 @@
%%
-spec start(context()) ->
{ok, context()} | no_return().
ok | no_return().
start(Context) ->
try call('Start', [?NS, ?ID, <<>>], Context) catch
{{exception, #'MachineAlreadyExists'{}}, Context1} ->
{ok, Context1}
error:#'MachineAlreadyExists'{} ->
ok
end.
-spec get_commit(dmt:version(), context()) ->
{dmt:commit() | {error, version_not_found}, context()} | no_return().
dmt:commit() | {error, version_not_found} | no_return().
get_commit(ID, Context) ->
dmt_api_context:map(
get_history(get_prev_commit(ID), 1, Context),
fun
(#{ID := Commit}) -> Commit;
(#{}) -> {error, version_not_found};
(Error) -> Error
end
).
case get_history(get_prev_commit(ID), 1, Context) of
#{ID := Commit} ->
Commit;
#{} ->
{error, version_not_found};
Error ->
Error
end.
get_prev_commit(1) ->
undefined;
@ -52,41 +52,48 @@ get_prev_commit(N) ->
%% TODO: add range requests after they are fixed in mg
-spec get_history(context()) ->
{dmt:history(), context()}.
dmt:history().
get_history(Context) ->
get_history(undefined, undefined, Context).
%% TODO: change this interface to accept dmt:version only
-spec get_history(dmt:version() | undefined, pos_integer() | undefined, context()) ->
{dmt:history() | {error, version_not_found}, context()}.
dmt:history() | {error, version_not_found}.
get_history(After, Limit, Context) ->
Range = #'HistoryRange'{'after' = prepare_event_id(After), 'limit' = Limit},
Descriptor = prepare_descriptor(?NS, ?REF, Range),
try dmt_api_context:map(call('GetMachine', [Descriptor], Context), fun read_history/1) catch
{{exception, #'EventNotFound'{}}, Context1} ->
{{error, version_not_found}, Context1}
try read_history(call('GetMachine', [Descriptor], Context)) catch
error:#'EventNotFound'{} ->
{error, version_not_found}
end.
-spec commit(dmt:version(), dmt:commit(), context()) ->
{dmt:version() | {error, version_not_found | operation_conflict}, context()}.
dmt:snapshot() | {error, version_not_found | operation_conflict}.
commit(Version, Commit, Context) ->
Descriptor = prepare_descriptor(?NS, ?REF, #'HistoryRange'{}),
Call = term_to_binary({commit, Version, Commit}),
dmt_api_context:map(call('Call', [Descriptor, Call], Context), fun binary_to_term/1).
binary_to_term(call('Call', [Descriptor, Call], Context)).
%%
-spec call(atom(), list(term()), context()) ->
{ok, context()} | {{ok, term()}, context()} | no_return().
-spec call(atom(), list(term()), context()) -> term() | no_return().
call(Method, Args, Context) ->
Request = {{dmsl_state_processing_thrift, 'Automaton'}, Method, Args},
{ok, URL} = application:get_env(dmt_api, automaton_service_url),
try
woody_client:call(Context, Request, #{url => URL})
catch
throw:{{exception, #'MachineNotFound'{}}, Context1} ->
{ok, Context2} = start(Context1),
woody_client:call(Context2, Request, #{url => URL})
Opts = #{url => URL, event_handler => {woody_event_handler_default, undefined}},
case woody_client:call(Request, Opts, Context) of
{ok, Result} ->
Result;
{exception, #'MachineNotFound'{}} ->
ok = start(Context),
case woody_client:call(Request, Opts, Context) of
{ok, Result} ->
Result;
{exception, Exception} ->
error(Exception)
end;
{exception, Exception} ->
error(Exception)
end.
%% utils

View File

@ -8,17 +8,17 @@
-include_lib("dmsl/include/dmsl_domain_config_thrift.hrl").
-spec handle_function(
woody_t:func(),
woody:func(),
woody_server_thrift_handler:args(),
woody_client:context(),
woody_server_thrift_handler:handler_opts()
) -> {woody_server_thrift_handler:result(), woody_client:context()} | no_return().
handle_function('checkoutObject', {Reference, ObjectReference}, Context, _Opts) ->
) -> {ok, woody_server_thrift_handler:result()} | no_return().
handle_function('checkoutObject', [Reference, ObjectReference], Context, _Opts) ->
case dmt_api:checkout_object(Reference, ObjectReference, Context) of
{Object = #'VersionedObject'{}, Context1} ->
{Object, Context1};
{{error, object_not_found}, Context1} ->
throw({#'ObjectNotFound'{}, Context1});
{{error, version_not_found}, Context1} ->
throw({#'VersionNotFound'{}, Context1})
Object = #'VersionedObject'{} ->
{ok, Object};
{error, object_not_found} ->
woody_error:raise(business, #'ObjectNotFound'{});
{error, version_not_found} ->
woody_error:raise(business, #'VersionNotFound'{})
end.

View File

@ -8,31 +8,31 @@
-include_lib("dmsl/include/dmsl_domain_config_thrift.hrl").
-spec handle_function(
woody_t:func(),
woody:func(),
woody_server_thrift_handler:args(),
woody_client:context(),
woody_server_thrift_handler:handler_opts()
) -> {woody_server_thrift_handler:result(), woody_client:context()} | no_return().
handle_function('Commit', {Version, Commit}, Context, _Opts) ->
) -> {ok, woody_server_thrift_handler:result()} | no_return().
handle_function('Commit', [Version, Commit], Context, _Opts) ->
case dmt_api:commit(Version, Commit, Context) of
{VersionNext, Context1} when is_integer(VersionNext) ->
{VersionNext, Context1};
{{error, operation_conflict}, Context1} ->
throw({#'OperationConflict'{}, Context1});
{{error, version_not_found}, Context1} ->
throw({#'VersionNotFound'{}, Context1})
VersionNext when is_integer(VersionNext) ->
{ok, VersionNext};
{error, operation_conflict} ->
woody_error:raise(business, #'OperationConflict'{});
{error, version_not_found} ->
woody_error:raise(business, #'VersionNotFound'{})
end;
handle_function('Checkout', {Reference}, Context, _Opts) ->
handle_function('Checkout', [Reference], Context, _Opts) ->
case dmt_api:checkout(Reference, Context) of
{Snapshot = #'Snapshot'{}, Context1} ->
{Snapshot, Context1};
{{error, version_not_found}, Context1} ->
throw({#'VersionNotFound'{}, Context1})
Snapshot = #'Snapshot'{} ->
{ok, Snapshot};
{error, version_not_found} ->
woody_error:raise(business, #'VersionNotFound'{})
end;
handle_function('Pull', {Version}, Context, _Opts) ->
handle_function('Pull', [Version], Context, _Opts) ->
case dmt_api:pull(Version, Context) of
{History = #{}, Context1} ->
{History, Context1};
{{error, version_not_found}, Context1} ->
throw({#'VersionNotFound'{}, Context1})
History = #{} ->
{ok, History};
{error, version_not_found} ->
woody_error:raise(business, #'VersionNotFound'{})
end.

View File

@ -9,40 +9,37 @@
-spec handle_function(
woody_t:func(),
woody:func(),
woody_server_thrift_handler:args(),
woody_client:context(),
woody_server_thrift_handler:handler_opts()
) -> {woody_server_thrift_handler:result(), woody_client:context()} | no_return().
handle_function('ProcessCall', {#'CallArgs'{arg = Payload, machine = Machine}}, Context, _Opts) ->
) -> {ok, woody_server_thrift_handler:result()} | no_return().
handle_function('ProcessCall', [#'CallArgs'{arg = Payload, machine = Machine}], _Context, _Opts) ->
{Response, Events} = handle_call(binary_to_term(Payload), dmt_api_mg:read_history(Machine)),
{
#'CallResult'{
change = #'MachineStateChange'{
aux_state = <<>>,
events = lists:map(fun term_to_binary/1, Events)
},
action = #'ComplexAction'{},
response = term_to_binary(Response)
{ok, #'CallResult'{
change = #'MachineStateChange'{
aux_state = <<>>,
events = lists:map(fun term_to_binary/1, Events)
},
Context
};
handle_function('ProcessSignal', {#'SignalArgs'{signal = {init, #'InitSignal'{}}}}, Context, _Opts) ->
{#'SignalResult'{
action = #'ComplexAction'{},
response = term_to_binary(Response)
}};
handle_function('ProcessSignal', [#'SignalArgs'{signal = {init, #'InitSignal'{}}}], _Context, _Opts) ->
{ok, #'SignalResult'{
change = #'MachineStateChange'{
aux_state = <<>>,
events = []
},
action = #'ComplexAction'{}
}, Context};
handle_function('ProcessSignal', {#'SignalArgs'{signal = {repair, #'RepairSignal'{}}}}, Context, _Opts) ->
{#'SignalResult'{
}};
handle_function('ProcessSignal', [#'SignalArgs'{signal = {repair, #'RepairSignal'{}}}], _Context, _Opts) ->
{ok, #'SignalResult'{
change = #'MachineStateChange'{
aux_state = <<>>,
events = []
},
action = #'ComplexAction'{}
}, Context}.
}}.
%%

View File

@ -1,21 +0,0 @@
-module(dmt_api_woody_event_handler).
-behaviour(woody_event_handler).
-export([handle_event/3]).
-spec handle_event(EventType, RpcID, EventMeta)
-> _ when
EventType :: woody_event_handler:event_type(),
RpcID :: woody_t:rpc_id(),
EventMeta :: woody_event_handler:event_meta_type().
handle_event(EventType, RpcID, #{status := error, class := Class, reason := Reason, stack := Stack}) ->
lager:error(
maps:to_list(RpcID),
"[server] ~s with ~s:~p at ~s",
[EventType, Class, Reason, genlib_format:format_stacktrace(Stack, [newlines])]
);
handle_event(EventType, RpcID, EventMeta) ->
lager:debug(maps:to_list(RpcID), "[server] ~s: ~p", [EventType, EventMeta]).