Packages

Core types for lattice CRDTs — version vectors, dot contexts, and causal infrastructure

Current section

Files

Jump to
lattice_core src lattice_core@dot_context.erl
Raw

src/lattice_core@dot_context.erl

-module(lattice_core@dot_context).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lattice_core/dot_context.gleam").
-export([new/0, add_dot/3, remove_dots/2, contains_dots/2]).
-export_type([dot/0, dot_context/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" A dot context tracks observed events (dots) across replicas.\n"
"\n"
" A \"dot\" is a pair of (replica_id, counter) uniquely identifying a single\n"
" write event. The dot context is used by causal CRDTs like MV-Register and\n"
" OR-Set to determine which operations have been observed and which can be\n"
" safely discarded during merge.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import lattice_core/dot_context.{Dot}\n"
" import lattice_core/replica_id\n"
"\n"
" let node_a = replica_id.new(\"node-a\")\n"
" let node_b = replica_id.new(\"node-b\")\n"
" let ctx = dot_context.new()\n"
" |> dot_context.add_dot(node_a, 1)\n"
" |> dot_context.add_dot(node_b, 1)\n"
" dot_context.contains_dots(ctx, [Dot(node_a, 1)]) // -> True\n"
" ```\n"
).
-type dot() :: {dot, lattice_core@replica_id:replica_id(), integer()}.
-opaque dot_context() :: {dot_context, gleam@set:set(dot())}.
-file("src/lattice_core/dot_context.gleam", 48).
?DOC(
" Create a new empty DotContext.\n"
"\n"
" Returns a context with no observed dots. Use `add_dot` to record events.\n"
).
-spec new() -> dot_context().
new() ->
{dot_context, gleam@set:new()}.
-file("src/lattice_core/dot_context.gleam", 56).
?DOC(
" Add a specific dot to the context.\n"
"\n"
" Records that the event `(replica_id, counter)` has been observed. If the\n"
" dot is already present, the context is returned unchanged.\n"
).
-spec add_dot(dot_context(), lattice_core@replica_id:replica_id(), integer()) -> dot_context().
add_dot(Context, Replica_id, Counter) ->
{dot_context,
gleam@set:insert(erlang:element(2, Context), {dot, Replica_id, Counter})}.
-file("src/lattice_core/dot_context.gleam", 68).
?DOC(
" Remove a list of dots from the context.\n"
"\n"
" Returns a new context with all dots in `dots` removed. Dots that are not\n"
" present are silently ignored.\n"
).
-spec remove_dots(dot_context(), list(dot())) -> dot_context().
remove_dots(Context, Dots) ->
{dot_context,
gleam@list:fold(
Dots,
erlang:element(2, Context),
fun(Acc, Dot) -> gleam@set:delete(Acc, Dot) end
)}.
-file("src/lattice_core/dot_context.gleam", 79).
?DOC(
" Check if all given dots are present in the context.\n"
"\n"
" Returns `True` only if every dot in `dots` has been observed (i.e., every\n"
" dot was previously added via `add_dot` and not subsequently removed).\n"
" Returns `True` for an empty `dots` list.\n"
).
-spec contains_dots(dot_context(), list(dot())) -> boolean().
contains_dots(Context, Dots) ->
gleam@list:all(
Dots,
fun(Dot) -> gleam@set:contains(erlang:element(2, Context), Dot) end
).