-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathgroot.ex
More file actions
67 lines (54 loc) · 2.04 KB
/
groot.ex
File metadata and controls
67 lines (54 loc) · 2.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
defmodule Groot do
@moduledoc """
Groot provides an eventually consistent, ephemeral KV store. It relies on
distributed erlang and uses LWW-registers and Hybrid-logical clocks
to ensure maximum availability. Groot utilizes ETS for efficient reading.
## Usage
```elixir
# Changes are propogated to other nodes.
:ok = Groot.set(:key, "value")
# Read existing values
"value" = Groot.get(:key)
```
Updates will replicate to all connected nodes. If a new node joins, or if a node
rejoins the cluster after a network partition then the other nodes in the
cluster will replicate all of their registers to the new node.
## Consistency
Groot uses LWW register CRDTs for storing values. Each register includes a
hybrid logical clock (HLC). Ordering of events is determined by comparing HLCs.
If a network partition occurs nodes on either side of the partition will
continue to accept `set` and `get` operations. Once the partition heals, all
registers will be replicated to all nodes. If there are any conflicts, the
register with the largest HLC will be chosen.
Groot may lose writes under specific failures scenarios. For instance, if
there is a network partition between 2 nodes, neither node will be able to
replicate to the other. If either node crashes after accepting a write, that
write will be lost.
## Data limitations
Groot replicates all keys to all connected nodes. Thus there may be performance
issues if you attempt to store hundreds or thousands of keys. This issue may
be fixed in a future release.
"""
alias Groot.Storage
@doc """
Gets a register's value. If the register is not found it returns `nil`.
"""
@spec get(term()) :: term() | nil
def get(key) do
Storage.get(key)
end
@doc """
Sets the value for a register.
"""
@spec set(term(), term(), term() | nil) :: :ok
def set(key, value, expires_in \\ nil) do
Storage.set(key, value, expires_in)
end
@doc """
Deletes a register
"""
@spec delete(term()) :: :ok
def delete(key) do
Storage.delete(key)
end
end