# Antidote CRDT library
[![Build Status](https://travis-ci.org/AntidoteDB/antidote_crdt.svg?branch=master)](https://travis-ci.org/AntidoteDB/antidote_crdt)
Operation based CRDT implementations to use with Antidote.
# API
The `antidote_crdt` module provides the API below.
For a more detailed description of the different data types, the [Antidote Documentation](http://syncfree.github.io/antidote/crdts.html) provides more information.
```erlang
% The CRDTs supported by Antidote:
-type typ() ::
antidote_crdt_counter_pn % PN-Counter aka Positive Negative Counter
| antidote_crdt_counter_b % Bounded Counter
| antidote_crdt_counter_fat % Fat Counter
| antidote_crdt_flag_ew % Enable Wins Flag aka EW-Flag
| antidote_crdt_flag_dw % Disable Wins Flag DW-Flag
| antidote_crdt_set_go % Grow Only Set aka G-Set
| antidote_crdt_set_aw % Add Wins Set aka AW-Set
| antidote_crdt_set_rw % Remove Wins Set aka RW-Set
| antidote_crdt_register_lww % Last Writer Wins Register aka LWW-Reg
| antidote_crdt_register_mv % MultiValue Register aka MV-Reg
| antidote_crdt_map_go % Grow Only Map aka G-Map
| antidote_crdt_map_rr. % Recursive Resets Map aka RR-Map
% The State of a CRDT:
-type crdt() :: ...
% The downstream effect, which has to be applied at each replica
-type effect() :: ...
% The update operation, consisting of operation name and parameters
% (e.g. {increment, 1} to increment a counter by one)
-type update() :: {atom(), term()}.
% Result of reading a CRDT (state without meta data)
-type value() :: term().
```
```erlang
% Check if the given type is supported by Antidote
-spec is_type(typ()) -> boolean().
% Returns the initial CRDT state for the given Type
-spec new(typ()) -> crdt().
% Reads the value from a CRDT state
-spec value(typ(), crdt()) -> any().
% Computes the downstream effect for a given update operation and current state.
% This has to be called once at the source replica.
% The effect must then be applied on all replicas using the update function.
% For some update operation it is not necessary to provide the current state
% and the atom 'ignore' can be passed instead (see function require_state_downstream).
-spec downstream(typ(), update(), crdt() | ignore) -> {ok, effect()} | {error, reason()}.
% Updates the state of a CRDT by applying a downstream effect calculated
% using the downstream function.
% For most types the update function must be called in causal order:
% if Eff2 was calculated on a state where Eff1 was already replied,
% then Eff1 has to be applied before Eff2 on all replicas.
-spec update(typ(), effect(), crdt()) -> {ok, crdt()}.
% Checks whether the current state is required by the downstream function
% for a specific type and update operation
-spec require_state_downstream(typ(), update()) -> boolean().
% Checks whether the given update operation is valid for the given type
-spec is_operation(typ(), update()) -> boolean().
```
# Development
Use the following `make` targets to build and test the CRDT library:
# compile
make compile
# run unit tests:
make test
# check types:
make dialyzer
# check code style:
make lint
## PropEr tests
To run the property based tests in the test directory install the [rebar3 PropEr plugin](https://www.rebar3.org/docs/using-available-plugins#proper) by adding the following line to `~/.config/rebar3/rebar.config`:
{plugins, [{rebar3_proper, "0.9.0"}]}.
Then execute the tests with:
make proper
For more control, you can run PropEr manually and specify parameters like the tested module or the number of generated tests:
rebar3 proper -n 1000 -m prop_crdt_orset