CP-12: Adds support for 'currency_conversion' config option (#28)

* CP-12: Adds support for 'currency_conversin' config option

* Fixes eunit tests

* Updates testcases in suites

* Fixes struct type in marshaling and temporarily disables codecov report upload

* Bumps damsel and limiter-proto

* Removes global 'currency_conversion' flag
This commit is contained in:
Aleksey Kashapov 2024-05-29 12:46:08 +03:00 committed by GitHub
parent 920d6ac31e
commit bcff0b78f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 99 additions and 75 deletions

View File

@ -37,3 +37,4 @@ jobs:
use-thrift: true use-thrift: true
thrift-version: ${{ needs.setup.outputs.thrift-version }} thrift-version: ${{ needs.setup.outputs.thrift-version }}
run-ct-with-compose: true run-ct-with-compose: true
upload-coverage: false

View File

@ -12,7 +12,7 @@
-spec call(service_name(), woody:func(), woody:args(), woody_context:ctx()) -> woody:result(). -spec call(service_name(), woody:func(), woody:args(), woody_context:ctx()) -> woody:result().
call(ServiceName, Function, Args, Context) -> call(ServiceName, Function, Args, Context) ->
EventHandler = scoper_woody_event_handler, EventHandler = {scoper_woody_event_handler, #{}},
call(ServiceName, Function, Args, Context, EventHandler). call(ServiceName, Function, Args, Context, EventHandler).
-spec call(service_name(), woody:func(), woody:args(), woody_context:ctx(), woody:ev_handler()) -> woody:result(). -spec call(service_name(), woody:func(), woody:args(), woody_context:ctx(), woody:ev_handler()) -> woody:result().

View File

@ -71,9 +71,15 @@ marshal_config(Config) ->
context_type = marshal_context_type(lim_config_machine:context_type(Config)), context_type = marshal_context_type(lim_config_machine:context_type(Config)),
type = maybe_apply(lim_config_machine:type(Config), fun marshal_type/1), type = maybe_apply(lim_config_machine:type(Config), fun marshal_type/1),
scope = maybe_apply(lim_config_machine:scope(Config), fun marshal_scope/1), scope = maybe_apply(lim_config_machine:scope(Config), fun marshal_scope/1),
op_behaviour = maybe_apply(lim_config_machine:op_behaviour(Config), fun marshal_op_behaviour/1) op_behaviour = maybe_apply(lim_config_machine:op_behaviour(Config), fun marshal_op_behaviour/1),
currency_conversion = marshal_currency_conversion(lim_config_machine:currency_conversion(Config))
}. }.
marshal_currency_conversion(true) ->
#config_CurrencyConversion{};
marshal_currency_conversion(_) ->
undefined.
marshal_op_behaviour(OpBehaviour) -> marshal_op_behaviour(OpBehaviour) ->
PaymentRefund = maps:get(invoice_payment_refund, OpBehaviour, undefined), PaymentRefund = maps:get(invoice_payment_refund, OpBehaviour, undefined),
#config_OperationLimitBehaviour{ #config_OperationLimitBehaviour{
@ -153,7 +159,8 @@ unmarshal('LimitConfigObject', #domain_LimitConfigObject{
type = Type, type = Type,
scopes = Scopes, scopes = Scopes,
description = Description, description = Description,
op_behaviour = OpBehaviour op_behaviour = OpBehaviour,
currency_conversion = CurrencyConversion
} }
}) -> }) ->
genlib_map:compact(#{ genlib_map:compact(#{
@ -167,7 +174,8 @@ unmarshal('LimitConfigObject', #domain_LimitConfigObject{
type => maybe_apply(Type, fun unmarshal_type/1), type => maybe_apply(Type, fun unmarshal_type/1),
scope => maybe_apply(Scopes, fun unmarshal_scope/1), scope => maybe_apply(Scopes, fun unmarshal_scope/1),
description => Description, description => Description,
op_behaviour => maybe_apply(OpBehaviour, fun unmarshal_op_behaviour/1) op_behaviour => maybe_apply(OpBehaviour, fun unmarshal_op_behaviour/1),
currency_conversion => CurrencyConversion =/= undefined
}). }).
unmarshal_timestamp(Timestamp) when is_binary(Timestamp) -> unmarshal_timestamp(Timestamp) when is_binary(Timestamp) ->
@ -196,7 +204,8 @@ unmarshal_params(#config_LimitConfigParams{
context_type = ContextType, context_type = ContextType,
type = Type, type = Type,
scope = Scope, scope = Scope,
op_behaviour = OpBehaviour op_behaviour = OpBehaviour,
currency_conversion = CurrencyConversion
}) -> }) ->
genlib_map:compact(#{ genlib_map:compact(#{
id => ID, id => ID,
@ -207,7 +216,8 @@ unmarshal_params(#config_LimitConfigParams{
type => maybe_apply(Type, fun unmarshal_type/1), type => maybe_apply(Type, fun unmarshal_type/1),
scope => maybe_apply(Scope, fun unmarshal_scope/1), scope => maybe_apply(Scope, fun unmarshal_scope/1),
description => Description, description => Description,
op_behaviour => maybe_apply(OpBehaviour, fun unmarshal_op_behaviour/1) op_behaviour => maybe_apply(OpBehaviour, fun unmarshal_op_behaviour/1),
currency_conversion => CurrencyConversion =/= undefined
}). }).
unmarshal_change({created, #config_CreatedChange{limit_config = Config}}) -> unmarshal_change({created, #config_CreatedChange{limit_config = Config}}) ->
@ -225,6 +235,7 @@ unmarshal_config(#config_LimitConfig{
type = TypeIn, type = TypeIn,
scope = Scope, scope = Scope,
op_behaviour = OpBehaviour, op_behaviour = OpBehaviour,
currency_conversion = CurrencyConversion,
body_type_deprecated = BodyTypeIn body_type_deprecated = BodyTypeIn
}) -> }) ->
Type = maybe_apply(TypeIn, fun unmarshal_type/1), Type = maybe_apply(TypeIn, fun unmarshal_type/1),
@ -240,7 +251,8 @@ unmarshal_config(#config_LimitConfig{
type => derive_type(Type, BodyType), type => derive_type(Type, BodyType),
scope => maybe_apply(Scope, fun unmarshal_scope/1), scope => maybe_apply(Scope, fun unmarshal_scope/1),
description => Description, description => Description,
op_behaviour => maybe_apply(OpBehaviour, fun unmarshal_op_behaviour/1) op_behaviour => maybe_apply(OpBehaviour, fun unmarshal_op_behaviour/1),
currency_conversion => CurrencyConversion =/= undefined
}). }).
derive_type(Type, undefined) -> derive_type(Type, undefined) ->
@ -359,7 +371,8 @@ marshal_unmarshal_created_test() ->
context_type => payment_processing, context_type => payment_processing,
type => {turnover, number}, type => {turnover, number},
scope => ordsets:from_list([party, shop]), scope => ordsets:from_list([party, shop]),
description => <<"description">> description => <<"description">>,
currency_conversion => false
}}, }},
Event = {ev, lim_time:machinery_now(), Created}, Event = {ev, lim_time:machinery_now(), Created},
?assertEqual(Event, unmarshal(timestamped_change, marshal(timestamped_change, Event))). ?assertEqual(Event, unmarshal(timestamped_change, marshal(timestamped_change, Event))).
@ -421,7 +434,8 @@ unmarshal_config_object_test() ->
context_type => payment_processing, context_type => payment_processing,
type => {turnover, number}, type => {turnover, number},
scope => ordsets:from_list([party, shop]), scope => ordsets:from_list([party, shop]),
description => <<"description">> description => <<"description">>,
currency_conversion => true
}, },
Object = #domain_LimitConfigObject{ Object = #domain_LimitConfigObject{
ref = #domain_LimitConfigRef{id = <<"id">>}, ref = #domain_LimitConfigRef{id = <<"id">>},
@ -437,7 +451,8 @@ unmarshal_config_object_test() ->
scopes = ordsets:from_list([ scopes = ordsets:from_list([
{'party', #limiter_config_LimitScopeEmptyDetails{}}, {'shop', #limiter_config_LimitScopeEmptyDetails{}} {'party', #limiter_config_LimitScopeEmptyDetails{}}, {'shop', #limiter_config_LimitScopeEmptyDetails{}}
]), ]),
description = <<"description">> description = <<"description">>,
currency_conversion = #limiter_config_CurrencyConversion{}
} }
}, },
?assertEqual(Config, unmarshal('LimitConfigObject', Object)). ?assertEqual(Config, unmarshal('LimitConfigObject', Object)).

View File

@ -17,6 +17,7 @@
-export([scope/1]). -export([scope/1]).
-export([context_type/1]). -export([context_type/1]).
-export([op_behaviour/1]). -export([op_behaviour/1]).
-export([currency_conversion/1]).
%% API %% API
@ -63,7 +64,8 @@
type := limit_type(), type := limit_type(),
scope => limit_scope(), scope => limit_scope(),
description => description(), description => description(),
op_behaviour => op_behaviour() op_behaviour => op_behaviour(),
currency_conversion => currency_conversion()
}. }.
-type create_params() :: #{ -type create_params() :: #{
@ -75,11 +77,13 @@
type => limit_type(), type => limit_type(),
scope => limit_scope(), scope => limit_scope(),
description => description(), description => description(),
op_behaviour => op_behaviour() op_behaviour => op_behaviour(),
current_function => currency_conversion()
}. }.
-type op_behaviour() :: #{operation_type() := addition | subtraction}. -type op_behaviour() :: #{operation_type() := addition | subtraction}.
-type operation_type() :: invoice_payment_refund. -type operation_type() :: invoice_payment_refund.
-type currency_conversion() :: boolean().
-type lim_id() :: limproto_limiter_thrift:'LimitID'(). -type lim_id() :: limproto_limiter_thrift:'LimitID'().
-type lim_version() :: dmsl_domain_thrift:'DataRevision'() | undefined. -type lim_version() :: dmsl_domain_thrift:'DataRevision'() | undefined.
@ -106,6 +110,7 @@
-export([process_call/4]). -export([process_call/4]).
-export([process_timeout/3]). -export([process_timeout/3]).
-export([process_repair/4]). -export([process_repair/4]).
-export([process_notification/4]).
-type timestamped_event(T) :: -type timestamped_event(T) ::
{ev, machinery:timestamp(), T}. {ev, machinery:timestamp(), T}.
@ -213,6 +218,12 @@ op_behaviour(#{op_behaviour := Value}) ->
op_behaviour(_) -> op_behaviour(_) ->
undefined. undefined.
-spec currency_conversion(config()) -> currency_conversion().
currency_conversion(#{currency_conversion := Value}) ->
Value;
currency_conversion(_) ->
false.
%% %%
-spec start(lim_id(), create_params(), lim_context()) -> {ok, config()}. -spec start(lim_id(), create_params(), lim_context()) -> {ok, config()}.
@ -650,6 +661,10 @@ process_timeout(_Machine, _HandlerArgs, _HandlerOpts) ->
process_repair(_Args, _Machine, _HandlerArgs, _HandlerOpts) -> process_repair(_Args, _Machine, _HandlerArgs, _HandlerOpts) ->
not_implemented(repair). not_implemented(repair).
-spec process_notification(args(_), machine(), handler_args(), handler_opts()) -> no_return().
process_notification(_Args, _Machine, _HandlerArgs, _HandlerOpts) ->
not_implemented(notification).
%%% Internal functions %%% Internal functions
emit_events(Events) -> emit_events(Events) ->

View File

@ -102,7 +102,8 @@ marshal_unmarshal_created_test() ->
context_type => payment_processing, context_type => payment_processing,
type => {turnover, {amount, <<"RUB">>}}, type => {turnover, {amount, <<"RUB">>}},
scope => ordsets:from_list([party]), scope => ordsets:from_list([party]),
description => <<"description">> description => <<"description">>,
currency_conversion => false
}}, }},
Context = #{machine_id => ID, machine_ns => config}, Context = #{machine_id => ID, machine_ns => config},
Event = {ev, lim_time:machinery_now(), Created}, Event = {ev, lim_time:machinery_now(), Created},

View File

@ -23,6 +23,7 @@
-export([process_call/4]). -export([process_call/4]).
-export([process_timeout/3]). -export([process_timeout/3]).
-export([process_repair/4]). -export([process_repair/4]).
-export([process_notification/4]).
-type args(T) :: machinery:args(T). -type args(T) :: machinery:args(T).
-type machine() :: machinery:machine(event(), _). -type machine() :: machinery:machine(event(), _).
@ -184,6 +185,10 @@ process_timeout(_Machine, _HandlerArgs, _HandlerOpts) ->
process_repair(_Args, _Machine, _HandlerArgs, _HandlerOpts) -> process_repair(_Args, _Machine, _HandlerArgs, _HandlerOpts) ->
not_implemented(repair). not_implemented(repair).
-spec process_notification(args(_), machine(), handler_args(), handler_opts()) -> no_return().
process_notification(_Args, _Machine, _HandlerArgs, _HandlerOpts) ->
not_implemented(notification).
%%% Internal functions %%% Internal functions
find_time_range(_TimeRange, []) -> find_time_range(_TimeRange, []) ->

View File

@ -51,9 +51,9 @@ get_commit_body(Config, LimitContext) ->
denominate(#{amount := Amount, currency := Currency}, Currency, _Config, _LimitContext) -> denominate(#{amount := Amount, currency := Currency}, Currency, _Config, _LimitContext) ->
{ok, Amount}; {ok, Amount};
denominate(Body = #{currency := Currency}, DestinationCurrency, Config, LimitContext) -> denominate(Body = #{currency := Currency}, DestinationCurrency, Config, LimitContext) ->
case genlib_app:env(limiter, currency_conversion, disabled) of case lim_config_machine:currency_conversion(Config) of
disabled -> currencies_mismatch_error(Currency, DestinationCurrency); false -> currencies_mismatch_error(Currency, DestinationCurrency);
enabled -> convert_currency(Body, DestinationCurrency, Config, LimitContext) true -> convert_currency(Body, DestinationCurrency, Config, LimitContext)
end. end.
currencies_mismatch_error(Currency, ExpectedCurrency) -> currencies_mismatch_error(Currency, ExpectedCurrency) ->

View File

@ -24,4 +24,4 @@ get_woody_client(Url) ->
-spec get_woody_event_handlers() -> woody:ev_handlers(). -spec get_woody_event_handlers() -> woody:ev_handlers().
get_woody_event_handlers() -> get_woody_event_handlers() ->
genlib_app:env(limiter, woody_event_handlers, [scoper_woody_event_handler]). genlib_app:env(limiter, woody_event_handlers, [{scoper_woody_event_handler, #{}}]).

View File

@ -37,7 +37,7 @@ init([]) ->
ok = application:set_env(limiter, backends, maps:from_list(Backends)), ok = application:set_env(limiter, backends, maps:from_list(Backends)),
RouteOptsEnv = genlib_app:env(?MODULE, route_opts, #{}), RouteOptsEnv = genlib_app:env(?MODULE, route_opts, #{}),
EventHandlers = genlib_app:env(?MODULE, woody_event_handlers, [woody_event_handler_default]), EventHandlers = genlib_app:env(?MODULE, woody_event_handlers, [{woody_event_handler_default, #{}}]),
EventHandlerOpts = genlib_app:env(?MODULE, scoper_event_handler_options, #{}), EventHandlerOpts = genlib_app:env(?MODULE, scoper_event_handler_options, #{}),
RouteOpts = RouteOptsEnv#{event_handler => {scoper_woody_event_handler, EventHandlerOpts}}, RouteOpts = RouteOptsEnv#{event_handler => {scoper_woody_event_handler, EventHandlerOpts}},

View File

@ -67,7 +67,7 @@ call(Function, Args, Client) ->
Call = {{limproto_limiter_thrift, 'Limiter'}, Function, Args}, Call = {{limproto_limiter_thrift, 'Limiter'}, Function, Args},
Opts = #{ Opts = #{
url => <<"http://limiter:8022/v1/limiter">>, url => <<"http://limiter:8022/v1/limiter">>,
event_handler => scoper_woody_event_handler, event_handler => {scoper_woody_event_handler, #{}},
transport_opts => #{ transport_opts => #{
max_connections => 10000 max_connections => 10000
} }
@ -79,7 +79,7 @@ call_configurator(Function, Args, Client) ->
Call = {{limproto_configurator_thrift, 'Configurator'}, Function, Args}, Call = {{limproto_configurator_thrift, 'Configurator'}, Function, Args},
Opts = #{ Opts = #{
url => <<"http://limiter:8022/v1/configurator">>, url => <<"http://limiter:8022/v1/configurator">>,
event_handler => scoper_woody_event_handler, event_handler => {scoper_woody_event_handler, #{}},
transport_opts => #{ transport_opts => #{
max_connections => 10000 max_connections => 10000
} }

View File

@ -138,7 +138,8 @@ create_config(C) ->
?scope_party() ?scope_party()
]), ]),
op_behaviour = ?op_behaviour(), op_behaviour = ?op_behaviour(),
context_type = ?ctx_type_payproc() context_type = ?ctx_type_payproc(),
currency_conversion = ?currency_conversion()
}, },
?assertMatch( ?assertMatch(
{ok, #config_LimitConfig{ {ok, #config_LimitConfig{
@ -159,7 +160,8 @@ create_config_single_scope(C) ->
type = ?lim_type_turnover(), type = ?lim_type_turnover(),
scope = {single, ?scope_party()}, scope = {single, ?scope_party()},
context_type = ?ctx_type_payproc(), context_type = ?ctx_type_payproc(),
op_behaviour = ?op_behaviour() op_behaviour = ?op_behaviour(),
currency_conversion = undefined
}, },
{ok, #config_LimitConfig{ {ok, #config_LimitConfig{
scope = Scope scope = Scope

View File

@ -68,6 +68,8 @@
invoice_payment_refund = Refund invoice_payment_refund = Refund
}). }).
-define(currency_conversion(), #config_CurrencyConversion{}).
-define(op_addition(), {addition, #config_Addition{}}). -define(op_addition(), {addition, #config_Addition{}}).
-define(op_subtraction(), {subtraction, #config_Subtraction{}}). -define(op_subtraction(), {subtraction, #config_Subtraction{}}).

View File

@ -44,7 +44,7 @@ mock_services_(Services, SupPid) when is_pid(SupPid) ->
Options = #{ Options = #{
ip => IP, ip => IP,
port => 0, port => 0,
event_handler => scoper_woody_event_handler, event_handler => {scoper_woody_event_handler, #{}},
handlers => lists:map(fun mock_service_handler/1, Services), handlers => lists:map(fun mock_service_handler/1, Services),
transport_opts => #{num_acceptors => 1} transport_opts => #{num_acceptors => 1}
}, },

View File

@ -76,7 +76,7 @@ all() ->
-spec groups() -> [{atom(), list(), [test_case_name()]}]. -spec groups() -> [{atom(), list(), [test_case_name()]}].
groups() -> groups() ->
[ [
{default, [], [ {base, [], [
commit_with_long_change_id, commit_with_long_change_id,
commit_with_default_exchange, commit_with_default_exchange,
partial_commit_with_exchange, partial_commit_with_exchange,
@ -93,11 +93,9 @@ groups() ->
commit_ok, commit_ok,
rollback_ok, rollback_ok,
partial_zero_commit_rollbacks, partial_zero_commit_rollbacks,
get_config_ok,
refund_ok, refund_ok,
commit_inexistent_hold_fails, commit_inexistent_hold_fails,
partial_commit_inexistent_hold_fails, partial_commit_inexistent_hold_fails,
commit_multirange_limit_ok,
commit_with_payment_tool_scope_ok, commit_with_payment_tool_scope_ok,
commit_with_party_scope_ok, commit_with_party_scope_ok,
commit_with_provider_scope_ok, commit_with_provider_scope_ok,
@ -105,33 +103,13 @@ groups() ->
commit_with_email_scope_ok, commit_with_email_scope_ok,
commit_with_multi_scope_ok commit_with_multi_scope_ok
]}, ]},
%% Repeats `default` group exept for `get_config_ok` and `commit_multirange_limit_ok` {default, [], [
{group, base},
get_config_ok,
commit_multirange_limit_ok
]},
{default_with_dominant, [], [ {default_with_dominant, [], [
commit_with_long_change_id, {group, base}
commit_with_default_exchange,
partial_commit_with_exchange,
commit_with_exchange,
hold_with_disabled_exchange,
rollback_with_wrong_currency,
hold_with_wrong_operation_context,
rollback_with_wrong_operation_context,
hold_with_wrong_payment_tool,
rollback_with_wrong_payment_tool,
get_limit_ok,
get_limit_notfound,
hold_ok,
commit_ok,
rollback_ok,
partial_zero_commit_rollbacks,
refund_ok,
commit_inexistent_hold_fails,
partial_commit_inexistent_hold_fails,
commit_with_payment_tool_scope_ok,
commit_with_party_scope_ok,
commit_with_provider_scope_ok,
commit_with_terminal_scope_ok,
commit_with_email_scope_ok,
commit_with_multi_scope_ok
]}, ]},
{withdrawals, [parallel], [ {withdrawals, [parallel], [
get_limit_ok, get_limit_ok,
@ -263,10 +241,11 @@ commit_with_long_change_id(C) ->
-spec commit_with_default_exchange(config()) -> _. -spec commit_with_default_exchange(config()) -> _.
commit_with_default_exchange(C) -> commit_with_default_exchange(C) ->
ok = application:set_env(limiter, currency_conversion, enabled),
Rational = #base_Rational{p = 1000000, q = 100}, Rational = #base_Rational{p = 1000000, q = 100},
_ = mock_exchange(Rational, C), _ = mock_exchange(Rational, C),
{ID, Version} = configure_limit(?time_range_month(), ?global(), C), {ID, Version} = configure_limit(
?time_range_month(), ?global(), ?turnover_metric_amount(<<"RUB">>), ?currency_conversion(), C
),
Cost = ?cash(10000, <<"SOME_CURRENCY">>), Cost = ?cash(10000, <<"SOME_CURRENCY">>),
Context = ?payproc_ctx_invoice(Cost), Context = ?payproc_ctx_invoice(Cost),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID, ?CHANGE_ID, Version), Context, ?config(client, C)), {ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID, ?CHANGE_ID, Version), Context, ?config(client, C)),
@ -274,10 +253,11 @@ commit_with_default_exchange(C) ->
-spec partial_commit_with_exchange(config()) -> _. -spec partial_commit_with_exchange(config()) -> _.
partial_commit_with_exchange(C) -> partial_commit_with_exchange(C) ->
ok = application:set_env(limiter, currency_conversion, enabled),
Rational = #base_Rational{p = 800000, q = 100}, Rational = #base_Rational{p = 800000, q = 100},
_ = mock_exchange(Rational, C), _ = mock_exchange(Rational, C),
{ID, Version} = configure_limit(?time_range_month(), ?global(), C), {ID, Version} = configure_limit(
?time_range_month(), ?global(), ?turnover_metric_amount(<<"RUB">>), ?currency_conversion(), C
),
Cost = ?cash(1000, <<"USD">>), Cost = ?cash(1000, <<"USD">>),
CaptureCost = ?cash(800, <<"USD">>), CaptureCost = ?cash(800, <<"USD">>),
Context = ?payproc_ctx_payment(Cost, CaptureCost), Context = ?payproc_ctx_payment(Cost, CaptureCost),
@ -286,10 +266,11 @@ partial_commit_with_exchange(C) ->
-spec commit_with_exchange(config()) -> _. -spec commit_with_exchange(config()) -> _.
commit_with_exchange(C) -> commit_with_exchange(C) ->
ok = application:set_env(limiter, currency_conversion, enabled),
Rational = #base_Rational{p = 1000000, q = 100}, Rational = #base_Rational{p = 1000000, q = 100},
_ = mock_exchange(Rational, C), _ = mock_exchange(Rational, C),
{ID, Version} = configure_limit(?time_range_month(), ?global(), C), {ID, Version} = configure_limit(
?time_range_month(), ?global(), ?turnover_metric_amount(<<"RUB">>), ?currency_conversion(), C
),
Cost = ?cash(10000, <<"USD">>), Cost = ?cash(10000, <<"USD">>),
Context = ?payproc_ctx_invoice(Cost), Context = ?payproc_ctx_invoice(Cost),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID, ?CHANGE_ID, Version), Context, ?config(client, C)), {ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID, ?CHANGE_ID, Version), Context, ?config(client, C)),
@ -297,7 +278,6 @@ commit_with_exchange(C) ->
-spec hold_with_disabled_exchange(config()) -> _. -spec hold_with_disabled_exchange(config()) -> _.
hold_with_disabled_exchange(C) -> hold_with_disabled_exchange(C) ->
ok = application:set_env(limiter, currency_conversion, disabled),
Rational = #base_Rational{p = 1000000, q = 100}, Rational = #base_Rational{p = 1000000, q = 100},
_ = mock_exchange(Rational, C), _ = mock_exchange(Rational, C),
ConfiguredCurrency = <<"RUB">>, ConfiguredCurrency = <<"RUB">>,
@ -310,7 +290,6 @@ hold_with_disabled_exchange(C) ->
-spec rollback_with_wrong_currency(config()) -> _. -spec rollback_with_wrong_currency(config()) -> _.
rollback_with_wrong_currency(C) -> rollback_with_wrong_currency(C) ->
ok = application:set_env(limiter, currency_conversion, disabled),
Rational = #base_Rational{p = 1000000, q = 100}, Rational = #base_Rational{p = 1000000, q = 100},
_ = mock_exchange(Rational, C), _ = mock_exchange(Rational, C),
ConfiguredCurrency = <<"RUB">>, ConfiguredCurrency = <<"RUB">>,
@ -750,6 +729,9 @@ configure_limit(TimeRange, Scope, C) ->
configure_limit(TimeRange, Scope, ?turnover_metric_amount(<<"RUB">>), C). configure_limit(TimeRange, Scope, ?turnover_metric_amount(<<"RUB">>), C).
configure_limit(TimeRange, Scope, Metric, C) -> configure_limit(TimeRange, Scope, Metric, C) ->
configure_limit(TimeRange, Scope, Metric, undefined, C).
configure_limit(TimeRange, Scope, Metric, CurrencyConversion, C) ->
ID = ?config(id, C), ID = ?config(id, C),
ContextType = ContextType =
case get_group_name(C) of case get_group_name(C) of
@ -764,7 +746,8 @@ configure_limit(TimeRange, Scope, Metric, C) ->
type = ?lim_type_turnover(Metric), type = ?lim_type_turnover(Metric),
scope = Scope, scope = Scope,
context_type = ContextType, context_type = ContextType,
op_behaviour = ?op_behaviour(?op_subtraction()) op_behaviour = ?op_behaviour(?op_subtraction()),
currency_conversion = CurrencyConversion
}, },
ConfigSource = proplists:get_value(limit_config_source, C, legacy), ConfigSource = proplists:get_value(limit_config_source, C, legacy),
put_config_into_repository(ConfigSource, CreateParams, ?config(client, C)). put_config_into_repository(ConfigSource, CreateParams, ?config(client, C)).

View File

@ -22,9 +22,6 @@
} }
}}, }},
% Enables currency conversion for turnover metric (default = disabled)
{currency_conversion, disabled},
{exchange_factors, #{ {exchange_factors, #{
<<"DEFAULT">> => {1, 1}, <<"DEFAULT">> => {1, 1},
<<"USD">> => {105, 100}, <<"USD">> => {105, 100},

View File

@ -12,7 +12,7 @@
{<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},2}, {<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},2},
{<<"damsel">>, {<<"damsel">>,
{git,"https://github.com/valitydev/damsel.git", {git,"https://github.com/valitydev/damsel.git",
{ref,"f718741970470474efcd32800daf885cb8d75584"}}, {ref,"02005deb9deb6470d2a17bb61e6b51098512f066"}},
0}, 0},
{<<"dmt_client">>, {<<"dmt_client">>,
{git,"https://github.com/valitydev/dmt_client.git", {git,"https://github.com/valitydev/dmt_client.git",
@ -24,7 +24,7 @@
1}, 1},
{<<"erl_health">>, {<<"erl_health">>,
{git,"https://github.com/valitydev/erlang-health.git", {git,"https://github.com/valitydev/erlang-health.git",
{ref,"7ffbc855bdbe79e23efad1803b0b185c9ea8d2f1"}}, {ref,"49716470d0e8dab5e37db55d52dea78001735a3d"}},
0}, 0},
{<<"genlib">>, {<<"genlib">>,
{git,"https://github.com/valitydev/genlib.git", {git,"https://github.com/valitydev/genlib.git",
@ -38,18 +38,18 @@
{<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},1}, {<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},1},
{<<"limiter_proto">>, {<<"limiter_proto">>,
{git,"https://github.com/valitydev/limiter-proto.git", {git,"https://github.com/valitydev/limiter-proto.git",
{ref,"e045813d32e67432e5592d582e59e45df05da647"}}, {ref,"1432a9871fc31b74c2af28b9367cb3ed6e08d498"}},
0}, 0},
{<<"machinery">>, {<<"machinery">>,
{git,"https://github.com/valitydev/machinery-erlang.git", {git,"https://github.com/valitydev/machinery-erlang.git",
{ref,"62c32434c80a462956ad9d50f9bce47836580d77"}}, {ref,"d62ceffbdb266bb4748bed34198e3575bba2dc73"}},
0}, 0},
{<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},2}, {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},2},
{<<"mg_proto">>, {<<"mg_proto">>,
{git,"https://github.com/valitydev/machinegun-proto.git", {git,"https://github.com/valitydev/machinegun-proto",
{ref,"347c5c44c8dcca24a50e0509c0df5401f863e790"}}, {ref,"3decc8f8b13c9cd1701deab47781aacddd7dbc92"}},
1}, 1},
{<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},2}, {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.3.0">>},2},
{<<"opentelemetry">>,{pkg,<<"opentelemetry">>,<<"1.3.0">>},0}, {<<"opentelemetry">>,{pkg,<<"opentelemetry">>,<<"1.3.0">>},0},
{<<"opentelemetry_api">>,{pkg,<<"opentelemetry_api">>,<<"1.2.1">>},0}, {<<"opentelemetry_api">>,{pkg,<<"opentelemetry_api">>,<<"1.2.1">>},0},
{<<"opentelemetry_exporter">>, {<<"opentelemetry_exporter">>,
@ -59,10 +59,11 @@
{pkg,<<"opentelemetry_semantic_conventions">>,<<"0.2.0">>}, {pkg,<<"opentelemetry_semantic_conventions">>,<<"0.2.0">>},
1}, 1},
{<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.3.1">>},2}, {<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.3.1">>},2},
{<<"prometheus">>,{pkg,<<"prometheus">>,<<"4.6.0">>},1},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.8.0">>},2}, {<<"ranch">>,{pkg,<<"ranch">>,<<"1.8.0">>},2},
{<<"scoper">>, {<<"scoper">>,
{git,"https://github.com/valitydev/scoper.git", {git,"https://github.com/valitydev/scoper.git",
{ref,"41a14a558667316998af9f49149ee087ffa8bef2"}}, {ref,"55a2a32ee25e22fa35f583a18eaf38b2b743429b"}},
0}, 0},
{<<"snowflake">>, {<<"snowflake">>,
{git,"https://github.com/valitydev/snowflake.git", {git,"https://github.com/valitydev/snowflake.git",
@ -79,7 +80,7 @@
{<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},2}, {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},2},
{<<"woody">>, {<<"woody">>,
{git,"https://github.com/valitydev/woody_erlang.git", {git,"https://github.com/valitydev/woody_erlang.git",
{ref,"5d46291a6bfcee0bae2a9346a7d927603a909249"}}, {ref,"81219ba5408e1c67f5eaed3c7e566ede42da88d4"}},
0}, 0},
{<<"xrates_proto">>, {<<"xrates_proto">>,
{git,"https://github.com/valitydev/xrates-proto.git", {git,"https://github.com/valitydev/xrates-proto.git",
@ -101,12 +102,13 @@
{<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>}, {<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>},
{<<"jsx">>, <<"D12516BAA0BB23A59BB35DCCAF02A1BD08243FCBB9EFE24F2D9D056CCFF71268">>}, {<<"jsx">>, <<"D12516BAA0BB23A59BB35DCCAF02A1BD08243FCBB9EFE24F2D9D056CCFF71268">>},
{<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>},
{<<"mimerl">>, <<"67E2D3F571088D5CFD3E550C383094B47159F3EEE8FFA08E64106CDF5E981BE3">>}, {<<"mimerl">>, <<"D0CD9FC04B9061F82490F6581E0128379830E78535E017F7780F37FEA7545726">>},
{<<"opentelemetry">>, <<"988AC3C26ACAC9720A1D4FB8D9DC52E95B45ECFEC2D5B5583276A09E8936BC5E">>}, {<<"opentelemetry">>, <<"988AC3C26ACAC9720A1D4FB8D9DC52E95B45ECFEC2D5B5583276A09E8936BC5E">>},
{<<"opentelemetry_api">>, <<"7B69ED4F40025C005DE0B74FCE8C0549625D59CB4DF12D15C32FE6DC5076FF42">>}, {<<"opentelemetry_api">>, <<"7B69ED4F40025C005DE0B74FCE8C0549625D59CB4DF12D15C32FE6DC5076FF42">>},
{<<"opentelemetry_exporter">>, <<"1D8809C0D4F4ACF986405F7700ED11992BCBDB6A4915DD11921E80777FFA7167">>}, {<<"opentelemetry_exporter">>, <<"1D8809C0D4F4ACF986405F7700ED11992BCBDB6A4915DD11921E80777FFA7167">>},
{<<"opentelemetry_semantic_conventions">>, <<"B67FE459C2938FCAB341CB0951C44860C62347C005ACE1B50F8402576F241435">>}, {<<"opentelemetry_semantic_conventions">>, <<"B67FE459C2938FCAB341CB0951C44860C62347C005ACE1B50F8402576F241435">>},
{<<"parse_trans">>, <<"16328AB840CC09919BD10DAB29E431DA3AF9E9E7E7E6F0089DD5A2D2820011D8">>}, {<<"parse_trans">>, <<"16328AB840CC09919BD10DAB29E431DA3AF9E9E7E7E6F0089DD5A2D2820011D8">>},
{<<"prometheus">>, <<"20510F381DB1CCAB818B4CF2FAC5FA6AB5CC91BC364A154399901C001465F46F">>},
{<<"ranch">>, <<"8C7A100A139FD57F17327B6413E4167AC559FBC04CA7448E9BE9057311597A1D">>}, {<<"ranch">>, <<"8C7A100A139FD57F17327B6413E4167AC559FBC04CA7448E9BE9057311597A1D">>},
{<<"ssl_verify_fun">>, <<"354C321CF377240C7B8716899E182CE4890C5938111A1296ADD3EC74CF1715DF">>}, {<<"ssl_verify_fun">>, <<"354C321CF377240C7B8716899E182CE4890C5938111A1296ADD3EC74CF1715DF">>},
{<<"tls_certificate_check">>, <<"C76C4C5D79EE79A2B11C84F910C825D6F024A78427C854F515748E9BD025E987">>}, {<<"tls_certificate_check">>, <<"C76C4C5D79EE79A2B11C84F910C825D6F024A78427C854F515748E9BD025E987">>},
@ -126,12 +128,13 @@
{<<"idna">>, <<"92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA">>}, {<<"idna">>, <<"92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA">>},
{<<"jsx">>, <<"0C5CC8FDC11B53CC25CF65AC6705AD39E54ECC56D1C22E4ADB8F5A53FB9427F3">>}, {<<"jsx">>, <<"0C5CC8FDC11B53CC25CF65AC6705AD39E54ECC56D1C22E4ADB8F5A53FB9427F3">>},
{<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>}, {<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>},
{<<"mimerl">>, <<"F278585650AA581986264638EBF698F8BB19DF297F66AD91B18910DFC6E19323">>}, {<<"mimerl">>, <<"A1E15A50D1887217DE95F0B9B0793E32853F7C258A5CD227650889B38839FE9D">>},
{<<"opentelemetry">>, <<"8E09EDC26AAD11161509D7ECAD854A3285D88580F93B63B0B1CF0BAC332BFCC0">>}, {<<"opentelemetry">>, <<"8E09EDC26AAD11161509D7ECAD854A3285D88580F93B63B0B1CF0BAC332BFCC0">>},
{<<"opentelemetry_api">>, <<"6D7A27B7CAD2AD69A09CABF6670514CAFCEC717C8441BEB5C96322BAC3D05350">>}, {<<"opentelemetry_api">>, <<"6D7A27B7CAD2AD69A09CABF6670514CAFCEC717C8441BEB5C96322BAC3D05350">>},
{<<"opentelemetry_exporter">>, <<"2B40007F509D38361744882FD060A8841AF772AB83BB542AA5350908B303AD65">>}, {<<"opentelemetry_exporter">>, <<"2B40007F509D38361744882FD060A8841AF772AB83BB542AA5350908B303AD65">>},
{<<"opentelemetry_semantic_conventions">>, <<"D61FA1F5639EE8668D74B527E6806E0503EFC55A42DB7B5F39939D84C07D6895">>}, {<<"opentelemetry_semantic_conventions">>, <<"D61FA1F5639EE8668D74B527E6806E0503EFC55A42DB7B5F39939D84C07D6895">>},
{<<"parse_trans">>, <<"07CD9577885F56362D414E8C4C4E6BDF10D43A8767ABB92D24CBE8B24C54888B">>}, {<<"parse_trans">>, <<"07CD9577885F56362D414E8C4C4E6BDF10D43A8767ABB92D24CBE8B24C54888B">>},
{<<"prometheus">>, <<"4905FD2992F8038ECCD7AA0CD22F40637ED618C0BED1F75C05AACEC15B7545DE">>},
{<<"ranch">>, <<"49FBCFD3682FAB1F5D109351B61257676DA1A2FDBE295904176D5E521A2DDFE5">>}, {<<"ranch">>, <<"49FBCFD3682FAB1F5D109351B61257676DA1A2FDBE295904176D5E521A2DDFE5">>},
{<<"ssl_verify_fun">>, <<"FE4C190E8F37401D30167C8C405EDA19469F34577987C76DDE613E838BBC67F8">>}, {<<"ssl_verify_fun">>, <<"FE4C190E8F37401D30167C8C405EDA19469F34577987C76DDE613E838BBC67F8">>},
{<<"tls_certificate_check">>, <<"4083B4A298ADD534C96125337CB01161C358BB32DD870D5A893AAE685FD91D70">>}, {<<"tls_certificate_check">>, <<"4083B4A298ADD534C96125337CB01161C358BB32DD870D5A893AAE685FD91D70">>},