Skip to content

Commit 2a8e7a0

Browse files
committed
khepri_tree: Ignore keep_while conditions on children on node creation
[Why] If a parent has a `keep_while` condition on a child node, the child node can't possibly exist when the parent is created. Therefore, ignore this condition when the parent is created because it will always be false. [How] Drop `keep_while` conditions on nodes that have the created node as prefix. While here, move this logic to its own function.
1 parent 39e1b90 commit 2a8e7a0

2 files changed

Lines changed: 45 additions & 4 deletions

File tree

src/khepri_tree.erl

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -655,11 +655,13 @@ insert_or_update_node(
655655
Path, Node, Payload, TreeOptions, Result),
656656
case Ret of
657657
{ok, Node1, Result1} when Result1 =/= #{} ->
658-
AbsKeepWhile = to_absolute_keep_while(
659-
Path, KeepWhile),
660-
KeepWhileOnOthers = maps:remove(Path, AbsKeepWhile),
658+
AbsKeepWhile0 = to_absolute_keep_while(
659+
Path, KeepWhile),
660+
AbsKeepWhile1 = (
661+
filter_out_irrelevant_keep_while_conds(
662+
Path, Node, AbsKeepWhile0)),
661663
KWMet = are_keep_while_conditions_met(
662-
Tree, KeepWhileOnOthers),
664+
Tree, AbsKeepWhile1),
663665
case KWMet of
664666
true ->
665667
{ok, Node1, {updated, Path, Result1}};
@@ -739,6 +741,22 @@ insert_or_update_node_cb(_, {interrupted, Reason, Info}, _, _, _) ->
739741
Reason1 = ?khepri_error(Reason, Info),
740742
{error, Reason1}.
741743

744+
filter_out_irrelevant_keep_while_conds(
745+
Path, {interrupted, node_not_found, #{node_is_target := true}}, KeepWhile) ->
746+
%% A `keep_while' condition on self is irrelevant if the node does not
747+
%% exist yet.
748+
KeepWhile1 = maps:remove(Path, KeepWhile),
749+
%% Likewise for `keep_while' conditions that apply to children of the
750+
%% node.
751+
KeepWhile2 = maps:filter(
752+
fun(KWPath, _) ->
753+
not lists:prefix(Path, KWPath)
754+
end, KeepWhile1),
755+
KeepWhile2;
756+
filter_out_irrelevant_keep_while_conds(
757+
_Path, _Node, KeepWhile) ->
758+
KeepWhile.
759+
742760
gather_node_props_from_old_and_new_nodes(OldNode, NewNode, TreeOptions) ->
743761
OldNodeProps = case OldNode of
744762
undefined ->

test/keep_while_conditions.erl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,29 @@ insert_when_keep_while_false_on_self_test() ->
188188
?assertEqual({ok, #{[foo] => #{}}}, Ret),
189189
?assertEqual([{aux, trigger_delayed_aux_queries_eval}], SE).
190190

191+
insert_when_keep_while_false_on_child_test() ->
192+
S0 = khepri_machine:init(?MACH_PARAMS()),
193+
KeepWhile = #{[?THIS_KHEPRI_NODE, bar] => #if_has_data{}},
194+
Command = #put{path = [foo],
195+
payload = khepri_payload:data(foo_value),
196+
options = #{keep_while => KeepWhile}},
197+
{S1, Ret, SE} = khepri_machine:apply(?META, Command, S0),
198+
Root = khepri_machine:get_root(S1),
199+
200+
?assertEqual(
201+
#node{
202+
props =
203+
#{payload_version => 1,
204+
child_list_version => 2},
205+
child_nodes =
206+
#{foo =>
207+
#node{
208+
props = ?INIT_NODE_PROPS,
209+
payload = khepri_payload:data(foo_value)}}},
210+
Root),
211+
?assertEqual({ok, #{[foo] => #{}}}, Ret),
212+
?assertEqual([{aux, trigger_delayed_aux_queries_eval}], SE).
213+
191214
keep_while_still_true_after_command_test() ->
192215
KeepWhile = #{[foo] => #if_child_list_length{count = 0}},
193216
Commands = [#put{path = [foo],

0 commit comments

Comments
 (0)