Skip to content

Commit

Permalink
projections: Add a test for effect ordering in transactions
Browse files Browse the repository at this point in the history
The parent commit changes the way we build side effect lists within a
transaction to use prepends instead of '++'/2. This case asserts that
we still process the effects in order when it comes to projections. If
we process effects out of order projections might behave strangely. A
simple example is that a deletion of a path in a transaction followed by
a put with new data should result in a projection on that path pattern
reflecting the new data. If we handled side effects out of order then
the projection table would be missing the record for that path instead.
  • Loading branch information
the-mikedavis committed Aug 26, 2024
1 parent 65d99a6 commit 23df91d
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions test/projections.erl
Original file line number Diff line number Diff line change
Expand Up @@ -801,3 +801,55 @@ old_unregister_projection_command_accepted_test() ->
?assertMatch(
{_S1, {ok, #{}}, _SE},
khepri_machine:apply(?META, Command, S0)).

trigger_projection_via_a_transaction_test_() ->
ProjectFun = fun(Path, Payload) -> {Path, Payload} end,
PathPattern = [stock, wood, <<"oak">>],
Data1 = 100,
Data2 = 100,
{setup,
fun() -> test_ra_server_helpers:setup(?FUNCTION_NAME) end,
fun(Priv) -> test_ra_server_helpers:cleanup(Priv) end,
[{inorder,
[{"Register the projection",
?_test(
begin
Projection = khepri_projection:new(?MODULE, ProjectFun),
?assertEqual(
ok,
khepri:register_projection(
?FUNCTION_NAME, PathPattern, Projection))
end)},

{"Trigger the projection with a non-transaction command",
?_assertEqual(
ok,
khepri:put(
?FUNCTION_NAME, PathPattern, Data1))},

{"The projection contains the triggered change",
?_assertEqual(Data1, ets:lookup_element(?MODULE, PathPattern, 2))},

{"Trigger the projection with a transaction",
?_assertEqual(
{ok, ok},
khepri:transaction(
?FUNCTION_NAME,
fun() ->
%% Issue a delete and then a put with the new data. This
%% case checks that the side effects which trigger
%% projections are accrued in the correct order within a
%% transaction.
%%
%% If the effects were accrued in the wrong order, the
%% next assertion would fail: if the effect(s) for delete
%% were processed after the put, the record would not
%% exist in the table. Instead it should exist and be
%% updated to `Data2'.
ok = khepri_tx:delete(PathPattern),
ok = khepri_tx:put(PathPattern, Data2)
end))},

{"The projection contains the triggered change",
?_assertEqual(Data2, ets:lookup_element(?MODULE, PathPattern, 2))}]
}]}.

0 comments on commit 23df91d

Please sign in to comment.