Packages
reckon_db
5.5.4
5.11.0
5.10.4
5.10.3
5.10.1
5.10.0
5.9.1
5.9.0
5.8.3
5.8.2
5.8.1
5.8.0
5.7.0
5.6.1
5.6.0
5.5.5
5.5.4
5.5.3
5.5.2
5.5.1
5.5.0
5.4.0
5.2.2
5.2.1
5.2.0
5.1.0
5.0.0
4.0.0
3.1.2
3.1.1
3.0.0
2.3.7
2.3.6
2.3.5
2.3.4
2.3.3
2.3.2
2.3.1
2.3.0
2.2.2
2.2.0
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.0
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.3
1.3.2
1.3.1
1.3.0
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.1
1.1.0
1.0.3
1.0.2
1.0.1
1.0.0
BEAM-native Event Store built on Khepri/Ra with Raft consensus. Event sourcing, persistent subscriptions, snapshots, and automatic cluster formation via UDP multicast discovery. Ships embedded Rust NIFs for 3-15x acceleration of crypto, hashing, compression, aggregation, filter matching, and grap...
Current section
Files
Jump to
Current section
Files
src/reckon_db_ccc_paths.erl
%%% @doc CCC (Command Context Consistency) Khepri path helpers.
%%%
%%% Payload index paths used by the CCC extensions to the DCB conditional-
%%% append primitive. Two structures live here:
%%%
%%% [by_payload, Key, Value, SeqKey] → #{} (single-field payload index)
%%% [by_payload_hash, Hash, SeqKey] → #{} (composite SHA-256 hash index)
%%%
%%% These are DCB-scoped (SeqKey-ordered, written atomically with each DCB
%%% event in the same Khepri transaction) and entirely separate from the
%%% secondary index under [idx, ...] which is OrderKey-keyed and optional.
%%%
%%% === Horus constraint ===
%%%
%%% All functions here EXCEPT payload_combo_hash/2 are PURE and safe to call
%%% from inside a khepri:transaction/2 body.
%%%
%%% payload_combo_hash/2 calls crypto:hash/2 — a NIF that Horus cannot
%%% extract into a portable Raft log entry. It MUST be called outside any
%%% transaction (in the stamp phase or via preprocess_filter/1).
%%%
%%% @end
-module(reckon_db_ccc_paths).
-include("reckon_db.hrl").
-include_lib("khepri/include/khepri.hrl").
-export([
by_payload_path/3,
by_payload_pattern/2,
by_payload_hash_path/2,
by_payload_hash_pattern/1,
payload_combo_hash/2
]).
%% @doc Path to a single-field payload index entry:
%% [by_payload, Key, Value, SeqKey]
-spec by_payload_path(binary(), binary(), non_neg_integer()) -> [term()].
by_payload_path(Key, Value, Seq)
when is_binary(Key), is_binary(Value), is_integer(Seq), Seq >= 0 ->
?BY_PAYLOAD_PATH ++ [Key, Value, reckon_db_dcb_paths:seq_key(Seq)].
%% @doc Pattern matching every seq under a payload field value (subtree wildcard).
%% Use with khepri_tx:get_many/1 inside a transaction.
-spec by_payload_pattern(binary(), binary()) -> [term()].
by_payload_pattern(Key, Value) when is_binary(Key), is_binary(Value) ->
?BY_PAYLOAD_PATH ++ [Key, Value, ?KHEPRI_WILDCARD_STAR].
%% @doc Path to a composite payload hash index entry:
%% [by_payload_hash, Hash, SeqKey]
-spec by_payload_hash_path(binary(), non_neg_integer()) -> [term()].
by_payload_hash_path(Hash, Seq)
when is_binary(Hash), is_integer(Seq), Seq >= 0 ->
?BY_PAYLOAD_HASH_PATH ++ [Hash, reckon_db_dcb_paths:seq_key(Seq)].
%% @doc Pattern matching every seq under a composite payload hash.
%% Use with khepri_tx:get_many/1 inside a transaction.
-spec by_payload_hash_pattern(binary()) -> [term()].
by_payload_hash_pattern(Hash) when is_binary(Hash) ->
?BY_PAYLOAD_HASH_PATH ++ [Hash, ?KHEPRI_WILDCARD_STAR].
%% @doc SHA-256 of the sorted [{Key, Value}] pair list.
%%
%% Sort ensures field-order independence: the same set of fields produces
%% the same hash regardless of the order Keys and Values are supplied.
%%
%% Example: payload_combo_hash([A, B], [V1, V2]) ==
%% payload_combo_hash([B, A], [V2, V1])
%%
%% MUST NOT be called from inside a Khepri transaction — crypto:hash/2 is a
%% NIF that Horus cannot extract. Pre-compute the hash in the stamp phase or
%% via reckon_db_ccc_filter:preprocess_filter/1 before entering the
%% transaction.
-spec payload_combo_hash([binary()], [binary()]) -> binary().
payload_combo_hash(Keys, Values)
when is_list(Keys), is_list(Values), length(Keys) =:= length(Values) ->
Pairs = lists:sort(lists:zip(Keys, Values)),
crypto:hash(sha256, term_to_binary(Pairs)).