OPS-161: Use modernizer facility to migrate domain-config (#20)

So that valitydev/damsel@09e7a75 might be dropped after migration.

* Bump to valitydev/machinery-erlang@19cdc6c
This commit is contained in:
Andrew Mayorov 2022-08-30 13:43:30 +03:00 committed by GitHub
parent 4e01fe45ba
commit 6f4ec7d9b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 404 additions and 117 deletions

View File

@ -63,10 +63,11 @@
{profiles, [
{test, [
{deps, [
{meck, "0.9.2"},
{dmt_client, {git, "https://github.com/valitydev/dmt-client.git", {ref, "ce6678a"}}}
]},
{dialyzer, [
{plt_extra_apps, [dmt_client]}
{plt_extra_apps, [meck, dmt_client]}
]}
]},
{prod, [

View File

@ -38,12 +38,12 @@
{<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},1},
{<<"machinery">>,
{git,"https://github.com/valitydev/machinery-erlang.git",
{ref,"4c0382f6cb14ebea361909c2a0e06efe0fc0d505"}},
{ref,"19cdc6c846f0ebf65ae193ca0988e353e53fe1d5"}},
0},
{<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},2},
{<<"mg_proto">>,
{git,"https://github.com/valitydev/machinegun-proto.git",
{ref,"a411c7d5d779389c70d2594eb4a28a916dce1721"}},
{git,"https://github.com/valitydev/machinegun-proto",
{ref,"96f7f11b184c29d8b7e83cd7646f3f2c13662bda"}},
1},
{<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},2},
{<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.3.1">>},2},

View File

@ -54,8 +54,8 @@ get_repository_handlers() ->
get_handler(repository_client, #{
repository => Repository,
default_handling_timeout => DefaultTimeout
}),
get_machinery_handler(Repository)
})
| get_machinery_handlers(Repository)
].
-spec get_handler(repository | repository_client | state_processor, woody:options()) ->
@ -71,15 +71,23 @@ get_handler(repository_client, Options) ->
{dmt_api_repository_client_handler, Options}
}}.
-spec get_machinery_handler(module()) ->
woody:http_handler(woody:th_handler()).
get_machinery_handler(Repository) ->
machinery_mg_backend:get_handler(
{Repository, #{
path => "/v1/stateproc",
backend_config => #{schema => Repository}
}}
).
-spec get_machinery_handlers(module()) ->
[woody:http_handler(woody:th_handler())].
get_machinery_handlers(Repository) ->
[
machinery_mg_backend:get_handler(
{Repository, #{
path => "/v1/stateproc",
backend_config => #{schema => Repository}
}}
),
machinery_modernizer_mg_backend:get_handler(
#{
path => <<"/v1/modernizer">>,
backend_config => #{schema => Repository}
}
)
].
-spec enable_health_logging(erl_health:check()) -> erl_health:check().
enable_health_logging(Check) ->

View File

@ -0,0 +1,48 @@
-module(dmt_api_repository_migration).
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-export([migrate/2]).
-type snapshot() :: dmt_api_repository:snapshot().
-type commit() :: dmt_api_repository:commit().
-type version() :: dmt_api_repository:version().
-spec migrate
(version(), commit()) -> commit();
(version(), snapshot()) -> snapshot().
migrate(1, Data) ->
migrate_legacy_payment_system_conditions(Data).
migrate_legacy_payment_system_conditions(Data) ->
% TODO OPS-161
% Relevant for https://github.com/valitydev/damsel/commit/09e7a75, revert this commit after
% complete migration.
% Replaces any `BankCardCondition` in a commit or snapshot which represents legacy payment
% system condition (i.e. one that compares against an atom in % `LegacyBankCardPaymentSystem`
% enum) with an empty `BankCardCondition`. Obviously, this incurs information loss yet
% significantly easier than proper mapping. Two reasons why this looks valid:
% - Production domain config do not contain legacy conditions anywhere in the last 3 months
% of snapshots.
% - https://github.com/valitydev/party-management since at least bb4549c won't handle them
% anyway.
genlib_ted:run(
fun
(Condition = #domain_BankCardCondition{}, _Annos) ->
{replace, migrate_legacy_payment_system_condition(Condition)};
(_, _Annos) ->
proceed
end,
Data
).
migrate_legacy_payment_system_condition(Condition) ->
case Condition#domain_BankCardCondition.definition of
{payment_system_is, Legacy} ->
true = is_atom(Legacy),
Condition#domain_BankCardCondition{definition = undefined};
{_, _} ->
Condition;
undefined ->
Condition
end.

View File

@ -41,6 +41,10 @@
-export([unmarshal/3]).
-export([get_version/1]).
%% NOTE
%% Used in migration tests.
-export([modernize/1]).
%%
-record(st, {
snapshot = #domain_conf_Snapshot{version = 0, domain = dmt_domain:new()} :: snapshot(),
@ -117,10 +121,17 @@ get_history_by_range(HistoryRange, WoodyCtx) ->
-spec get_backend(woody_context:ctx()) -> machinery_mg_backend:backend().
get_backend(WoodyCtx) ->
machinery_mg_backend:new(WoodyCtx, #{
machinery_mg_backend:new(WoodyCtx, get_backend_config()).
-spec get_modernizer_backend(woody_context:ctx()) -> machinery_modernizer_mg_backend:backend().
get_modernizer_backend(WoodyCtx) ->
machinery_modernizer_mg_backend:new(WoodyCtx, get_backend_config()).
get_backend_config() ->
#{
client => dmt_api_woody_utils:get_woody_client(automaton),
schema => ?MODULE
}).
}.
%%
@ -230,6 +241,10 @@ make_event(Snapshot, Commit) ->
%%
-spec modernize(woody_context:ctx()) -> ok.
modernize(WoodyCtx) ->
machinery_modernizer:modernize(?NS, ?ID, get_modernizer_backend(WoodyCtx)).
-spec marshal(machinery_mg_schema:t(), machinery_mg_schema:v(_), machinery_mg_schema:context()) ->
{machinery_msgpack:t(), machinery_mg_schema:context()}.
marshal({event, FmtVsn}, V, C) ->
@ -252,26 +267,53 @@ unmarshal({response, call}, V, C) ->
unmarshal(T, V, C) ->
machinery_mg_schema_generic:unmarshal(T, V, C).
%%
-spec get_version(machinery_mg_schema:vt()) -> machinery_mg_schema:version().
get_version(_) ->
1.
% NOTE
% Current format version.
% Be aware, this function is being mocked in the testsuite.
2.
encode_event_data(1 = FmtVsn, {commit, Commit, Meta}) ->
encode_event_data(FmtVsn, {commit, CommitIn, Meta}) ->
% NOTE
% Ensure that outdated commit won't sneak in.
Commit = migrate(1, get_version(event), commit, CommitIn),
{arr, [{str, <<"commit">>}, encode(commit, Commit), encode_commit_meta(FmtVsn, Meta)]}.
encode_commit_meta(1, #{snapshot := Snapshot}) ->
encode_commit_meta(_FmtVsn, #{snapshot := SnapshotIn}) ->
% NOTE
% Ensure that outdated snapshot won't sneak in.
Snapshot = migrate(1, get_version(event), snapshot, SnapshotIn),
{obj, #{{str, <<"snapshot">>} => encode(snapshot, Snapshot)}};
encode_commit_meta(1, #{}) ->
encode_commit_meta(_FmtVsn, #{}) ->
{obj, #{}}.
decode_event_data(1 = FmtVsn, {arr, [{str, <<"commit">>}, Commit, Meta]}) ->
{commit, decode(commit, Commit), decode_commit_meta(FmtVsn, Meta)}.
decode_event_data(FmtVsn, {arr, [{str, <<"commit">>}, CommitEnc, Meta]}) when
is_integer(FmtVsn), FmtVsn > 0
->
Commit = migrate(FmtVsn, get_version(event), commit, decode(commit, CommitEnc)),
{commit, Commit, decode_commit_meta(FmtVsn, Meta)}.
decode_commit_meta(1, {obj, #{{str, <<"snapshot">>} := Snapshot}}) ->
#{snapshot => decode(snapshot, Snapshot)};
decode_commit_meta(1, {obj, #{}}) ->
decode_commit_meta(FmtVsn, {obj, #{{str, <<"snapshot">>} := SnapshotEnc}}) ->
Snapshot = migrate(FmtVsn, get_version(event), snapshot, decode(snapshot, SnapshotEnc)),
#{snapshot => Snapshot};
decode_commit_meta(_FmtVsn, {obj, #{}}) ->
#{}.
migrate(TargetVsn, TargetVsn, _Type, Data) ->
% Nothing to migrate.
Data;
migrate(Vsn, TargetVsn, Type, Data) when Vsn < TargetVsn ->
Migrated = dmt_api_repository_migration:migrate(Vsn, Data),
ok = validate(Type, Migrated),
migrate(Vsn + 1, TargetVsn, Type, Migrated).
validate(T, V) ->
_ = encode(T, V),
ok.
%%
encode_call({commit, Version, Commit}) ->

View File

@ -0,0 +1,193 @@
-module(dmt_api_migration_tests_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_conf_thrift.hrl").
-export([all/0]).
-export([init_per_suite/1]).
-export([end_per_suite/1]).
-export([init_per_testcase/2]).
-export([end_per_testcase/2]).
-export([fv2_migration_succeeds/1]).
-export([fv2_modernization_succeeds/1]).
-type config() :: [{atom(), term()}].
-type test_case_name() :: atom().
-define(CONF(Key, C), (element(2, lists:keyfind(Key, 1, C)))).
-define(REPOSITORY, dmt_api_repository_v5).
%%
-spec all() -> [test_case_name()].
all() ->
[
fv2_migration_succeeds,
fv2_modernization_succeeds
].
-spec init_per_suite(config()) -> config().
init_per_suite(C) ->
Apps1 = genlib_app:start_application_with(scoper, [
{storage, scoper_storage_logger}
]),
Apps2 = genlib_app:start_application_with(dmt_api, [
{repository, ?REPOSITORY},
% NOTE
% Effectively disable cache altogether so it won't spoil testcase expectations.
% Keep in mind that in production setting this cache will certainly affect migrations'
% visibility.
{max_cache_size, 0},
{services, #{
automaton => #{
url => "http://machinegun:8022/v1/automaton"
}
}}
]),
Apps3 = genlib_app:start_application_with(dmt_client, [
{max_cache_size, #{
elements => 1,
memory => 102400
}},
{service_urls, #{
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">>
}}
]),
ok = logger:set_primary_config(level, info),
[{suite_apps, Apps1 ++ Apps2 ++ Apps3} | C].
-spec end_per_suite(config()) -> term().
end_per_suite(C) ->
genlib_app:stop_unload_applications(?CONF(suite_apps, C)).
-spec init_per_testcase(test_case_name(), config()) -> config().
init_per_testcase(Name, C) ->
_ = meck:unload(),
WoodyCtx = woody_context:new(mk_rpc_id(Name)),
[{woody_ctx, WoodyCtx}, {dmt_client_opts, #{woody_context => WoodyCtx}} | C].
mk_rpc_id(Name) ->
TraceID = genlib:format("~s:~p", [Name, erlang:system_time(millisecond)]),
woody_context:new_rpc_id(<<"undefined">>, TraceID, woody_context:new_req_id()).
-spec end_per_testcase(test_case_name(), config()) -> _.
end_per_testcase(_, _) ->
ok.
%%
-define(FMT_VSN_INITIAL, 1).
-define(FMT_VSN_TARGET, 2).
-define(LEGACY_CONDITION,
{payment_tool,
{bank_card, #domain_BankCardCondition{
definition = {payment_system_is, uzcard}
}}}
).
-define(TARGET_CONDITION,
{payment_tool,
{bank_card, #domain_BankCardCondition{
definition = undefined
}}}
).
-spec fv2_migration_succeeds(config()) -> _.
fv2_migration_succeeds(C) ->
ClientOpts = ?CONF(dmt_client_opts, C),
ok = meck:new(dmt_api_repository_v5, [passthrough]),
ok = meck:expect(dmt_api_repository_v5, get_version, fun(_) -> ?FMT_VSN_INITIAL end),
Version1 = get_latest_version(ClientOpts),
ObjectRef1 = #domain_CriterionRef{id = dmt_ct_helper:next_id()},
Commit1 = dmt_ct_helper:mk_insert_commit(
{criterion, #domain_CriterionObject{
ref = ObjectRef1,
data = #domain_Criterion{
name = <<"Legacy Criterion 1">>,
predicate = {condition, ?LEGACY_CONDITION}
}
}}
),
Version2 = dmt_client_api:commit(Version1, Commit1, ClientOpts),
ok = meck:expect(dmt_api_repository_v5, get_version, fun(_) -> ?FMT_VSN_TARGET end),
Snapshot2 = checkout(Version2, ClientOpts),
?assertMatch(
{criterion, #domain_CriterionObject{
data = #domain_Criterion{
predicate = {condition, ?TARGET_CONDITION}
}
}},
get_domain_object({criterion, ObjectRef1}, Snapshot2)
),
ObjectRef2 = #domain_CriterionRef{id = dmt_ct_helper:next_id()},
Commit2 = dmt_ct_helper:mk_insert_commit(
{criterion, #domain_CriterionObject{
ref = ObjectRef2,
data = #domain_Criterion{
name = <<"Legacy Criterion 2">>,
predicate = {condition, ?LEGACY_CONDITION}
}
}}
),
Version3 = dmt_client_api:commit(Version2, Commit2, ClientOpts),
Snapshot3 = checkout(Version3, ClientOpts),
?assertMatch(
{criterion, #domain_CriterionObject{
data = #domain_Criterion{
predicate = {condition, ?TARGET_CONDITION}
}
}},
get_domain_object({criterion, ObjectRef2}, Snapshot3)
),
ok = meck:unload(dmt_api_repository_v5).
-spec fv2_modernization_succeeds(config()) -> _.
fv2_modernization_succeeds(C) ->
ClientOpts = ?CONF(dmt_client_opts, C),
ok = meck:new(dmt_api_repository_v5, [passthrough]),
ok = meck:expect(dmt_api_repository_v5, get_version, fun(_) -> ?FMT_VSN_INITIAL end),
Version1 = get_latest_version(ClientOpts),
ObjectRef = #domain_CriterionRef{id = dmt_ct_helper:next_id()},
Commit = dmt_ct_helper:mk_insert_commit(
{criterion, #domain_CriterionObject{
ref = ObjectRef,
data = #domain_Criterion{
name = <<"Legacy Criterion">>,
predicate = {condition, ?LEGACY_CONDITION}
}
}}
),
Version2 = dmt_client_api:commit(Version1, Commit, #{}),
ok = meck:expect(dmt_api_repository_v5, get_version, fun(_) -> ?FMT_VSN_TARGET end),
ok = dmt_api_repository_v5:modernize(?CONF(woody_ctx, C)),
Snapshot2 = checkout(Version2, ClientOpts),
?assertMatch(
{criterion, #domain_CriterionObject{
data = #domain_Criterion{
predicate = {condition, ?TARGET_CONDITION}
}
}},
get_domain_object({criterion, ObjectRef}, Snapshot2)
),
ok = meck:unload(dmt_api_repository_v5).
%%
checkout(head, ClientOpts) ->
dmt_client_api:checkout({head, #domain_conf_Head{}}, ClientOpts);
checkout(Version, ClientOpts) when is_integer(Version) ->
dmt_client_api:checkout({version, Version}, ClientOpts).
get_latest_version(ClientOpts) ->
Snapshot = checkout(head, ClientOpts),
Snapshot#domain_conf_Snapshot.version.
get_domain_object(ObjectRef, #domain_conf_Snapshot{domain = Domain}) ->
maps:get(ObjectRef, Domain).

View File

@ -154,10 +154,7 @@ insert(_C) ->
Ref = fixture_object_ref(ID),
#domain_conf_ObjectNotFound{} = (catch dmt_client:checkout_object(Ref)),
#domain_conf_Snapshot{version = Version1} = dmt_client:checkout(latest),
Version2 = dmt_client:commit(
Version1,
#domain_conf_Commit{ops = [{insert, #domain_conf_InsertOp{object = Object}}]}
),
Version2 = dmt_client:insert(Version1, Object),
_ = dmt_client_cache:update(),
Object = dmt_client:checkout_object(Ref),
#domain_conf_ObjectNotFound{} = (catch dmt_client:checkout_object(Version1, Ref)),
@ -170,14 +167,8 @@ update(_C) ->
Object2 = fixture_domain_object(ID, <<"UpdateFixture2">>),
Ref = fixture_object_ref(ID),
#domain_conf_Snapshot{version = Version0} = dmt_client:checkout(latest),
Version1 = dmt_client:commit(
Version0,
#domain_conf_Commit{ops = [{insert, #domain_conf_InsertOp{object = Object1}}]}
),
Version2 = dmt_client:commit(
Version1,
#domain_conf_Commit{ops = [{update, #domain_conf_UpdateOp{old_object = Object1, new_object = Object2}}]}
),
Version1 = dmt_client:commit(Version0, dmt_ct_helper:mk_insert_commit(Object1)),
Version2 = dmt_client:commit(Version1, dmt_ct_helper:mk_update_commit(Object1, Object2)),
_ = dmt_client_cache:update(),
Object1 = dmt_client:checkout_object(Version1, Ref),
Object2 = dmt_client:checkout_object(Version2, Ref).
@ -188,14 +179,8 @@ delete(_C) ->
Object = fixture_domain_object(ID, <<"DeleteFixture">>),
Ref = fixture_object_ref(ID),
#domain_conf_Snapshot{version = Version0} = dmt_client:checkout(latest),
Version1 = dmt_client:commit(
Version0,
#domain_conf_Commit{ops = [{insert, #domain_conf_InsertOp{object = Object}}]}
),
Version2 = dmt_client:commit(
Version1,
#domain_conf_Commit{ops = [{remove, #domain_conf_RemoveOp{object = Object}}]}
),
Version1 = dmt_client:commit(Version0, dmt_ct_helper:mk_insert_commit(Object)),
Version2 = dmt_client:commit(Version1, dmt_ct_helper:mk_remove_commit(Object)),
Object = dmt_client:checkout_object(Version1, Ref),
#domain_conf_ObjectNotFound{} = (catch dmt_client:checkout_object(Version2, Ref)).
@ -205,31 +190,23 @@ pull_commit(_C) ->
History1 = #{} = dmt_client:pull_range(0, ?DEFAULT_LIMIT),
Version1 = lists:max([0 | maps:keys(History1)]),
Object = fixture_domain_object(ID, <<"PullFixture">>),
Commit = #domain_conf_Commit{ops = [{insert, #domain_conf_InsertOp{object = Object}}]},
Commit = dmt_ct_helper:mk_insert_commit(Object),
Version2 = dmt_client:commit(Version1, Commit),
#{Version2 := Commit} = dmt_client:pull_range(Version1, ?DEFAULT_LIMIT).
-spec retry_commit(term()) -> term().
retry_commit(_C) ->
Commit1 = #domain_conf_Commit{
ops = [
{insert, #domain_conf_InsertOp{
object = fixture_domain_object(next_id(), <<"RetryCommitFixture">>)
}}
]
},
Commit1 = dmt_ct_helper:mk_insert_commit(
fixture_domain_object(next_id(), <<"RetryCommitFixture">>)
),
#domain_conf_Snapshot{version = Version1} = dmt_client:checkout(latest),
Version2 = dmt_client:commit(Version1, Commit1),
Version2 = Version1 + 1,
Version2 = dmt_client:commit(Version1, Commit1),
#domain_conf_Snapshot{version = Version2} = dmt_client:checkout(latest),
Commit2 = #domain_conf_Commit{
ops = [
{insert, #domain_conf_InsertOp{
object = fixture_domain_object(next_id(), <<"RetryCommitFixture">>)
}}
]
},
Commit2 = dmt_ct_helper:mk_insert_commit(
fixture_domain_object(next_id(), <<"RetryCommitFixture">>)
),
Version3 = dmt_client:commit(Version2, Commit2),
Version3 = Version2 + 1,
Version2 = dmt_client:commit(Version1, Commit1),
@ -240,34 +217,20 @@ missing_version(_C) ->
#domain_conf_Snapshot{version = Version1} = dmt_client:checkout(latest),
_ = ?assertThrow(
#domain_conf_VersionNotFound{},
dmt_client:commit(
dmt_client:insert(
Version1 + 42,
#domain_conf_Commit{
ops = [
{insert, #domain_conf_InsertOp{
object = fixture_domain_object(next_id(), <<"MissingVersionFixture">>)
}}
]
}
fixture_domain_object(next_id(), <<"MissingVersionFixture">>)
)
).
-spec obsolete(term()) -> term().
obsolete(_C) ->
Commit1 = #domain_conf_Commit{
ops = [
{insert, #domain_conf_InsertOp{
object = fixture_domain_object(next_id(), <<"InitialFixture">>)
}}
]
},
Commit2 = #domain_conf_Commit{
ops = [
{insert, #domain_conf_InsertOp{
object = fixture_domain_object(next_id(), <<"ObsoleteFixture">>)
}}
]
},
Commit1 = dmt_ct_helper:mk_insert_commit(
fixture_domain_object(next_id(), <<"InitialFixture">>)
),
Commit2 = dmt_ct_helper:mk_insert_commit(
fixture_domain_object(next_id(), <<"ObsoleteFixture">>)
),
#domain_conf_Snapshot{version = Version1} = dmt_client:checkout(latest),
_Version2 = dmt_client:commit(Version1, Commit1),
_ = ?assertThrow(
@ -285,27 +248,22 @@ conflict_notfound(_C) ->
object_ref = {criterion, #domain_CriterionRef{id = 42}}
}}
},
dmt_client:commit(Version1, #domain_conf_Commit{
ops = [
{update, #domain_conf_UpdateOp{
old_object = criterion_w_refs(42, []),
new_object = criterion_w_refs(42, [43, 44, 45])
}}
]
})
dmt_client:commit(
Version1,
dmt_ct_helper:mk_update_commit(
criterion_w_refs(42, []),
criterion_w_refs(42, [43, 44, 45])
)
)
).
-spec conflict_exists(term()) -> term().
conflict_exists(_C) ->
ID = next_id(),
Ref = fixture_object_ref(ID),
Commit = #domain_conf_Commit{
ops = [
{insert, #domain_conf_InsertOp{
object = fixture_domain_object(ID, <<"ExistingObjectFixture">>)
}}
]
},
Commit = dmt_ct_helper:mk_insert_commit(
fixture_domain_object(ID, <<"ExistingObjectFixture">>)
),
#domain_conf_Snapshot{version = Version1} = dmt_client:checkout(latest),
Version2 = dmt_client:commit(Version1, Commit),
_ = ?assertThrow(
@ -322,24 +280,17 @@ conflict_mismatch(_C) ->
Object1 = fixture_domain_object(ID1, <<"Original">>),
Ref2 = fixture_object_ref(ID2),
#domain_conf_Snapshot{version = Version1} = dmt_client:checkout(latest),
Version2 = dmt_client:commit(
Version1,
#domain_conf_Commit{ops = [{insert, #domain_conf_InsertOp{object = Object1}}]}
),
Version2 = dmt_client:commit(Version1, dmt_ct_helper:mk_insert_commit(Object1)),
_ = ?assertThrow(
#domain_conf_OperationConflict{
conflict = {object_reference_mismatch, #domain_conf_ObjectReferenceMismatchConflict{object_ref = Ref2}}
},
dmt_client:commit(
Version2,
#domain_conf_Commit{
ops = [
{update, #domain_conf_UpdateOp{
old_object = Object1,
new_object = fixture_domain_object(ID2, <<"Mismatch">>)
}}
]
}
dmt_ct_helper:mk_update_commit(
Object1,
fixture_domain_object(ID2, <<"Mismatch">>)
)
)
).
@ -394,10 +345,7 @@ checkout_object(_C) ->
Object = fixture_domain_object(ID, <<"InsertFixture">>),
Ref = fixture_object_ref(ID),
#domain_conf_Snapshot{version = Version1} = dmt_client:checkout(latest),
Version2 = dmt_client:commit(
Version1,
#domain_conf_Commit{ops = [{insert, #domain_conf_InsertOp{object = Object}}]}
),
Version2 = dmt_client:insert(Version1, Object),
?assertEqual(
{ok, #domain_conf_VersionedObject{version = Version2, object = Object}},
call_checkout_object({head, #domain_conf_Head{}}, Ref)
@ -416,9 +364,7 @@ checkout_object(_C) ->
).
next_id() ->
16#7FFFFFFF band
(erlang:system_time(millisecond) * 1000 +
erlang:unique_integer([positive, monotonic])).
dmt_ct_helper:next_id().
fixture_domain_object(Ref, Data) ->
{category, #domain_CategoryObject{

42
test/dmt_ct_helper.erl Normal file
View File

@ -0,0 +1,42 @@
-module(dmt_ct_helper).
-include_lib("damsel/include/dmsl_domain_conf_thrift.hrl").
-export([mk_insert_commit/1]).
-export([mk_update_commit/2]).
-export([mk_remove_commit/1]).
-export([next_id/0]).
-type object() :: dmsl_domain_thrift:'DomainObject'().
-type commit() :: dmt_api_repository:commit().
-spec mk_insert_commit(object() | [object()]) -> commit().
mk_insert_commit(Objects) when is_list(Objects) ->
#domain_conf_Commit{
ops = [{insert, #domain_conf_InsertOp{object = Object}} || Object <- Objects]
};
mk_insert_commit(Object) when is_tuple(Object) ->
mk_insert_commit([Object]).
-spec mk_update_commit(_Old :: object(), _New :: object()) -> commit().
mk_update_commit(Old, New) when is_tuple(Old), is_tuple(New) ->
#domain_conf_Commit{
ops = [{update, #domain_conf_UpdateOp{old_object = Old, new_object = New}}]
}.
-spec mk_remove_commit(object() | [object()]) -> commit().
mk_remove_commit(Objects) when is_list(Objects) ->
#domain_conf_Commit{
ops = [{remove, #domain_conf_RemoveOp{object = Object}} || Object <- Objects]
};
mk_remove_commit(Object) when is_tuple(Object) ->
mk_remove_commit([Object]).
%%
-spec next_id() -> 0..16#7FFFFFFF.
next_id() ->
16#7FFFFFFF band
(erlang:system_time(millisecond) * 1000 +
erlang:unique_integer([positive, monotonic])).

View File

@ -5,5 +5,12 @@ namespaces:
domain-config:
processor:
url: http://dominant:8022/v1/stateproc
modernizer:
# NOTE
# Knowingly greater than any reasonable format version so that modernizing
# always considers every event as outdated.
current_format_version: 9999
handler:
url: http://dominant:8022/v1/modernizer
storage:
type: memory