Skip to content

Commit

Permalink
Implement LWWRegister
Browse files Browse the repository at this point in the history
  • Loading branch information
abangratz committed Oct 9, 2023
1 parent b7b692f commit 9a1e017
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
74 changes: 74 additions & 0 deletions lib/crdt/lww_register.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
defmodule CRDT.LWWRegister do
@moduledoc """
A last-write-wins register
Is used to store simple values with a timestamp. Using `merge` on two registers
will result in creating a register with the value corresponding to the most
recent timestamp
"""

@type t :: %CRDT.LWWRegister{
value: term | nil,
timestamp: {pos_integer(), pos_integer(), pos_integer()}
}

defstruct value: nil, timestamp: :os.timestamp()

@doc """
Creates a new register with the value set to the supplied parameter or nil
and the current timestamp as returned by `:os.timestamp/0`
iex> CRDT.LWWRegister.new()
%CRDT.LWWRegister{value: nil}
iex> CRDT.LWWRegister.new("data")
%CRDT.LWWRegister{value: "data"}
"""
@spec new :: t
def(new(), do: %CRDT.LWWRegister{})

@spec new(term) :: t
def new(data), do: %CRDT.LWWRegister{value: data}

@doc """
Sets the value of the register to the supplied parameter and updates the
timestamp to the current timestamp as returned by `:os.timestamp/0`
iex> CRDT.LWWRegister.new() |> CRDT.LWWRegister.set("data")
...> |> CRDT.value()
"data"
"""
@spec set(t, term) :: t
def set(register, data) do
%CRDT.LWWRegister{register | value: data, timestamp: :os.timestamp()}
end
end

defimpl CRDT, for: CRDT.LWWRegister do
@doc """
Returns the value of the register
iex> CRDT.LWWRegister.new("data") |> CRDT.value()
"data"
"""
def value(register), do: register.value

@doc """
Merges two registers and returns a new register with the value corresponding
to the most recent timestamp
iex> CRDT.LWWRegister.new("data") |> CRDT.merge(CRDT.LWWRegister.new("data2"))
...> |> CRDT.value()
"data2"
"""

def merge(register1, register2) do
if register1.timestamp > register2.timestamp do
register1
else
register2
end
end
end
5 changes: 5 additions & 0 deletions test/crdt/lww_register_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule CRDT.LWWRegisterTest do
use ExUnit.Case
doctest CRDT.LWWRegister
doctest CRDT.CRDT.LWWRegister
end

0 comments on commit 9a1e017

Please sign in to comment.