Condition support.
Conditions can be used in path patterns and keep_while
conditions. They
allow to point to a specific node only if conditions are met, or to match
several tree nodes with a single path pattern.
A condition is an Erlang record defining a specific property. Some of them have arguments to further define the condition.
All supported conditions are described in the Data Types section.comparison_op(Type) = {eq, Type} | {ne, Type} | {lt, Type} | {le, Type} | {gt, Type} | {ge, Type}
Comparison operator in some condition()
.
condition() = if_name_matches() | if_path_matches() | if_has_data() | if_data_matches() | if_node_exists() | if_payload_version() | if_child_list_version() | if_child_list_length() | if_not() | if_all() | if_any()
All supported conditions.
if_all() = #if_all{conditions = [khepri_path:pattern_component()]}
Condition. Evaluates to true if all inner conditions evaluate to true.
Record fields:conditions
: a list of inner conditions to evaluate.#if_all{conditions = [#if_name_matches{regex = "^a"},
#if_has_data{has_data = true}]}.
if_any() = #if_any{conditions = [khepri_path:pattern_component()]}
Condition. Evaluates to true if any of the inner conditions evaluate to true.
Record fields:conditions
: a list of inner conditions to evaluate.#if_any{conditions = [#if_name_matches{regex = "^a"},
#if_has_data{has_data = true}]}.
if_child_list_length() = #if_child_list_length{count = non_neg_integer() | khepri_condition:comparison_op(non_neg_integer())}
Condition. Evaluates to true if the tested node's child list size corresponds to the expected value.
Record fields:version
: integer or comparison_op()
to compare to the actual
child list child.#if_child_list_length{count = 1}.
#if_child_list_length{count = {gt, 10}}.
if_child_list_version() = #if_child_list_version{version = khepri:child_list_version() | khepri_condition:comparison_op(khepri:child_list_version())}
Condition. Evaluates to true if the tested node's child list version corresponds to the expected value.
Record fields:version
: integer or comparison_op()
to compare to the actual
child list version.#if_child_list_version{version = 1}.
#if_child_list_version{version = {gt, 10}}.
if_data_matches() = #if_data_matches{pattern = ets:match_pattern(), conditions = [any()], compiled = ets:comp_match_spec() | undefined}
Condition. Evaluates to true if the tested node has a data payload and the
data payload term matches the given pattern
and all conditions
evaluates
to true.
pattern
: an ETS-like match pattern. The match pattern can define
variables to be used in the conditions
below.conditions
: a list of guard expressions. All guard expressions must
evaluate to true to consider a match. The default is an empty list of
conditions which means that only the pattern matching is
considered.%% The data must be of the form `{user, _}', so a tuple of arity 2 with the
%% first element being the `user' atom. The second element can be anything.
#if_data_matches{pattern = {user, '_'}}.
%% The data must be of the form `{age, Age}' and `Age' must be an
%% integer greater than or equal to 18.
#if_data_matches{pattern = {age, '$1'},
conditions = [{is_integer, '$1'},
{'>=', '$1', 18}]}.
See Match
Specifications in Erlang for a detailed documentation of how it works.
if_has_data() = #if_has_data{has_data = boolean()}
Condition. Evaluates to true if the tested node's data payload presence corresponds to the expected state.
Record fields:has_data
: boolean set to the expected presence of a data
payload.Data absence is either no payload or a non-data type of payload.
Example:#if_has_data{has_data = false}.
if_name_matches() = #if_name_matches{regex = any | iodata() | unicode:charlist(), compiled = re_mp() | undefined}
Condition. Evaluates to true if the name of the tested node matches the condition pattern.
Record fields:regex
: defines the condition pattern. It can be either:
any
to match any node names; the equivalent of the ".*"
regular expression but more efficient#if_name_matches{regex = "^user_"}.
#if_name_matches{regex = any}.
if_node_exists() = #if_node_exists{exists = boolean()}
Condition. Evaluates to true if the tested node existence corresponds to the expected state.
Record fields:exists
: boolean set to the expected presence of the node.#if_node_exists{exists = false}.
if_not() = #if_not{condition = khepri_path:pattern_component()}
Condition. Evaluates to true if the inner condition evaluates to false.
Record fields:condition
: the inner condition to evaluate.#if_not{condition = #if_name_matches{regex = "^a"}}.
if_path_matches() = #if_path_matches{regex = any | iodata() | unicode:charlist(), compiled = re_mp() | undefined}
Condition. Evaluates to true if the name of the tested node matches the condition pattern. If it does not match, child node names are tested recursively.
Record fields:regex
: defines the condition pattern. It can be either:
any
to match any node names; the equivalent of the ".*"
regular expression but more efficient#if_path_matches{regex = "^user_"}.
#if_path_matches{regex = any}.
if_payload_version() = #if_payload_version{version = khepri:payload_version() | khepri_condition:comparison_op(khepri:payload_version())}
Condition. Evaluates to true if the tested node's payload version corresponds to the expected value.
Record fields:version
: integer or comparison_op()
to compare to the actual
payload version.#if_payload_version{version = 1}.
#if_payload_version{version = {gt, 10}}.
keep_while() = #{khepri_path:path() => condition()}
An association between a path and a condition. As long as the condition evaluates to true, the tree node is kept. Once the condition evaluates to false, the tree node is deleted.
If the keep_while
conditions are false at the time of the insert, the
insert fails. The only exception to that is if the keep_while
condition
is on the inserted node itself.
Paths in the map can be native paths or Unix-like paths. However, having two entries that resolve to the same node (one native path entry and one Unix-like path entry for instance) is undefined behavior: one of them will overwrite the other.
Example:khepri:put(
StoreId,
[foo],
Payload,
#{keep_while => #{
%% The node `[foo]' will be removed as soon as `[bar]' is removed
%% because the condition associated with `[bar]' will not be true
%% anymore.
[bar] => #if_node_exists{exists = true}
}}
).
native_keep_while() = #{khepri_path:native_path() => condition()}
An association between a native path and a condition.
This is the same askeep_while()
but the paths in the map keys were
converted to native paths if necessary.
re_mp() = tuple()
ensure_native_keep_while/1 |
ensure_native_keep_while(KeepWhile) -> NativeKeepWhile
KeepWhile = keep_while()
NativeKeepWhile = native_keep_while()
Generated by EDoc