Search documentation of macula

# macula_crdt (macula v0.44.2)

View Source

Conflict-Free Replicated Data Types (CRDTs) for shared state.

Implements CRDTs for eventually-consistent distributed state management: - LWW-Register (Last-Write-Wins Register) - single value with timestamp - OR-Set (Observed-Remove Set) - set with add/remove semantics - G-Counter (Grow-only Counter) - monotonically increasing counter - PN-Counter (Positive-Negative Counter) - increment/decrement counter

These CRDTs replace Ra/Raft consensus for Macula's masterless architecture. State is synchronized via gossip protocol between nodes.

# Summary

## Types

gcounter/0
lww_register/0
or_set/0
pncounter/0
timestamp/0
unique_tag/0

## Functions

gcounter_increment(Counter)

Increment the G-Counter by 1 for current node

gcounter_increment(Counter, N)

Increment the G-Counter by N for current node

gcounter_merge(C1, C2)

Merge two G-Counters (take max of each node's count)

gcounter_value(Counter)

Get the total value of the G-Counter

lww_get(_)

Get the current value of the LWW-Register

lww_merge(R1, R2)

Merge two LWW-Registers Keeps the value with the highest timestamp Ties broken by node name (lexicographic order)

lww_set(Register, Value, Timestamp)

Set a value in the LWW-Register with timestamp

lww_timestamp(_)

Get the timestamp of the LWW-Register

lww_value(Register)

Get the value of the LWW-Register (alias for lww_get)

new_gcounter()

Create a new G-Counter

new_lww_register()

Create a new empty LWW-Register

new_lww_register(Value)

Create a new LWW-Register with initial value

new_or_set()

Create a new empty OR-Set

new_pncounter()

Create a new PN-Counter

or_add(Set, Element)

Add an element to the OR-Set (auto-generates unique tag)

or_add(_, Element, Tag)

Add an element to the OR-Set with a specific tag

or_contains(_, Element)

Check if element is in the OR-Set

or_elements(_)

Get all elements in the OR-Set

or_merge(_, _)

Merge two OR-Sets Union of elements, union of tombstones

or_remove(Set, Element)

Remove an element from the OR-Set Removes all current tags for that element (add-wins semantics)

or_size(Set)

Get the number of elements in the OR-Set

pncounter_decrement(Counter)

Decrement the PN-Counter by 1

pncounter_decrement(_, Amount)

Decrement the PN-Counter by N

pncounter_increment(Counter)

Increment the PN-Counter by 1

pncounter_increment(_, Amount)

Increment the PN-Counter by N

pncounter_merge(_, _)

Merge two PN-Counters

pncounter_value(_)

Get the value of the PN-Counter (positive - negative)

# Types

# gcounter/0

    -type gcounter() :: #{node() => non_neg_integer()}.

# lww_register/0

    -type lww_register() :: #{value => term(), timestamp => timestamp(), node => node()}.

# or_set/0

    -type or_set() ::
              #{elements => #{term() => sets:set(unique_tag())}, tombstones => sets:set(unique_tag())}.

# pncounter/0

    -type pncounter() :: #{p => gcounter(), n => gcounter()}.

# timestamp/0

    -type timestamp() :: non_neg_integer().

# unique_tag/0

    -type unique_tag() :: binary().

# Functions

# gcounter_increment(Counter)

    -spec gcounter_increment(gcounter()) -> gcounter().

Increment the G-Counter by 1 for current node

# gcounter_increment(Counter, N)

    -spec gcounter_increment(gcounter(), pos_integer()) -> gcounter().

Increment the G-Counter by N for current node

# gcounter_merge(C1, C2)

    -spec gcounter_merge(gcounter(), gcounter()) -> gcounter().

Merge two G-Counters (take max of each node's count)

# gcounter_value(Counter)

    -spec gcounter_value(gcounter()) -> non_neg_integer().

Get the total value of the G-Counter

# lww_get(_)

    -spec lww_get(lww_register()) -> term().

Get the current value of the LWW-Register

# lww_merge(R1, R2)

    -spec lww_merge(lww_register(), lww_register()) -> lww_register().

Merge two LWW-Registers Keeps the value with the highest timestamp Ties broken by node name (lexicographic order)

# lww_set(Register, Value, Timestamp)

    -spec lww_set(lww_register(), term(), timestamp()) -> lww_register().

Set a value in the LWW-Register with timestamp

# lww_timestamp(_)

    -spec lww_timestamp(lww_register()) -> timestamp().

Get the timestamp of the LWW-Register

# lww_value(Register)

    -spec lww_value(lww_register()) -> term().

Get the value of the LWW-Register (alias for lww_get)

# new_gcounter()

    -spec new_gcounter() -> gcounter().

Create a new G-Counter

# new_lww_register()

    -spec new_lww_register() -> lww_register().

Create a new empty LWW-Register

# new_lww_register(Value)

    -spec new_lww_register(term()) -> lww_register().

Create a new LWW-Register with initial value

# new_or_set()

    -spec new_or_set() -> or_set().

Create a new empty OR-Set

# new_pncounter()

    -spec new_pncounter() -> pncounter().

Create a new PN-Counter

# or_add(Set, Element)

    -spec or_add(or_set(), term()) -> or_set().

Add an element to the OR-Set (auto-generates unique tag)

# or_add(_, Element, Tag)

    -spec or_add(or_set(), term(), unique_tag()) -> or_set().

Add an element to the OR-Set with a specific tag

# or_contains(_, Element)

    -spec or_contains(or_set(), term()) -> boolean().

Check if element is in the OR-Set

# or_elements(_)

    -spec or_elements(or_set()) -> [term()].

Get all elements in the OR-Set

# or_merge(_, _)

    -spec or_merge(or_set(), or_set()) -> or_set().

Merge two OR-Sets Union of elements, union of tombstones

# or_remove(Set, Element)

    -spec or_remove(or_set(), term()) -> or_set().

Remove an element from the OR-Set Removes all current tags for that element (add-wins semantics)

# or_size(Set)

    -spec or_size(or_set()) -> non_neg_integer().

Get the number of elements in the OR-Set

# pncounter_decrement(Counter)

    -spec pncounter_decrement(pncounter()) -> pncounter().

Decrement the PN-Counter by 1

# pncounter_decrement(_, Amount)

    -spec pncounter_decrement(pncounter(), pos_integer()) -> pncounter().

Decrement the PN-Counter by N

# pncounter_increment(Counter)

    -spec pncounter_increment(pncounter()) -> pncounter().

Increment the PN-Counter by 1

# pncounter_increment(_, Amount)

    -spec pncounter_increment(pncounter(), pos_integer()) -> pncounter().

Increment the PN-Counter by N

# pncounter_merge(_, _)

    -spec pncounter_merge(pncounter(), pncounter()) -> pncounter().

Merge two PN-Counters

# pncounter_value(_)

    -spec pncounter_value(pncounter()) -> integer().

Get the value of the PN-Counter (positive - negative)