Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement LWWRegister #2

Merged
merged 3 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/crdt.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ defprotocol CRDT do
Protocol defining the interface for CRDTs.
"""

@type actor :: term()
@type key :: term()
@type crdt :: term()

@doc """
Returns the actual value of the CRDT
"""
@spec value(t) :: term
@spec value(t()) :: term()
def value(crdt)

@doc """
Merges two CRDTs.
"""
@spec merge(t, t) :: t
@spec merge(t(), t()) :: t()
def merge(crdt1, crdt2)
end
6 changes: 3 additions & 3 deletions lib/crdt/access.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
defprotocol CRDT.Access do
@spec get_in(t, nonempty_list(term)) :: term
@spec get_in(t(), nonempty_list(term())) :: term()
def get_in(t, list)
@spec put_in(t, term, nonempty_list(term), CRDT.crdt()) :: CRDT.crdt()
@spec put_in(t(), term(), nonempty_list(term()), CRDT.crdt()) :: CRDT.crdt()
def put_in(t, actor, list, value)
@spec update_in(t, term, nonempty_list(term), (term -> term)) :: CRDT.crdt()
@spec update_in(t(), term(), nonempty_list(term()), (term() -> term())) :: CRDT.crdt()
def update_in(t, actor, list, fun)
end
20 changes: 8 additions & 12 deletions lib/crdt/awor_map.ex
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
defmodule CRDT.AWORMap do
@moduledoc false

@type actor :: term
@type key :: term
@type crdt :: term

@type t :: %__MODULE__{
keys: CRDT.AWORSet.t(),
entries: %{key => crdt}
entries: %{CRDT.key() => CRDT.crdt()}
}

defstruct keys: CRDT.AWORSet.new(), entries: %{}
Expand All @@ -28,7 +24,7 @@ defmodule CRDT.AWORMap do
entries: %{}
}
"""
@spec new() :: t
@spec new() :: t()
def new, do: %__MODULE__{}

@doc """
Expand All @@ -47,7 +43,7 @@ defmodule CRDT.AWORMap do
entries: %{key: %CRDT.GCounter{}}
}
"""
@spec put(t, actor, key, crdt) :: t
@spec put(t(), CRDT.actor(), CRDT.key(), CRDT.crdt()) :: t()
def put(%__MODULE__{keys: keys, entries: entries}, actor, key, crdt) do
CRDT.impl_for!(crdt)

Expand All @@ -67,7 +63,7 @@ defmodule CRDT.AWORMap do
...> |> CRDT.AWORMap.fetch(:key)
{:ok, %CRDT.GCounter{}}
"""
@spec fetch(t, key) :: {:ok, crdt} | :error
@spec fetch(t(), CRDT.key()) :: {:ok, CRDT.crdt()} | :error
def fetch(%__MODULE__{entries: entries}, key), do: Map.fetch(entries, key)

@doc """
Expand All @@ -86,7 +82,7 @@ defmodule CRDT.AWORMap do
iex> CRDT.AWORMap.new() |> CRDT.AWORMap.fetch!(:key)
** (KeyError) key :key not found in: %{}
"""
@spec fetch!(t, key) :: crdt
@spec fetch!(t(), CRDT.key()) :: CRDT.crdt()
def fetch!(%__MODULE__{entries: entries}, key), do: Map.fetch!(entries, key)

@doc """
Expand All @@ -102,7 +98,7 @@ defmodule CRDT.AWORMap do
...> |> CRDT.AWORMap.get(:key, CRDT.GCounter.new())
%CRDT.GCounter{}
"""
@spec get(t, key, crdt) :: crdt
@spec get(t(), CRDT.key(), CRDT.crdt()) :: CRDT.crdt()
def get(%__MODULE__{entries: entries}, key, default \\ nil), do: Map.get(entries, key, default)

@doc """
Expand All @@ -125,7 +121,7 @@ defmodule CRDT.AWORMap do
...> |> CRDT.value()
%{key: 5}
"""
@spec update(t, actor, key, crdt, (crdt -> crdt)) :: t
@spec update(t(), CRDT.actor(), CRDT.key(), CRDT.crdt(), (CRDT.crdt() -> CRDT.crdt())) :: t()
def update(%__MODULE__{entries: entries} = awor_map, actor, key, default, fun)
when is_function(fun) do
CRDT.impl_for!(default)
Expand Down Expand Up @@ -161,7 +157,7 @@ defmodule CRDT.AWORMap do
...> |> CRDT.value()
** (KeyError) key :key not found in: %{}
"""
@spec update!(t, actor, key, (crdt -> crdt)) :: t
@spec update!(t(), CRDT.actor(), CRDT.key(), (CRDT.crdt() -> CRDT.crdt())) :: t()
def update!(%__MODULE__{entries: entries} = awor_map, actor, key, fun)
when is_function(fun) do
crdt = Map.fetch!(entries, key)
Expand Down
6 changes: 3 additions & 3 deletions lib/crdt/awor_set.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule CRDT.AWORSet do
}
}
"""
@spec new() :: t
@spec new() :: t()
def new, do: %__MODULE__{}

@doc """
Expand All @@ -39,7 +39,7 @@ defmodule CRDT.AWORSet do
}
}
"""
@spec add(t, actor, value) :: t
@spec add(t(), actor(), value()) :: t()
def add(%__MODULE__{dot_kernel: dot_kernel}, actor, value) do
%__MODULE__{
dot_kernel:
Expand All @@ -62,7 +62,7 @@ defmodule CRDT.AWORSet do
}
}
"""
@spec remove(t, value) :: t
@spec remove(t(), value()) :: t()
def remove(%__MODULE__{dot_kernel: dot_kernel}, value) do
%__MODULE__{dot_kernel: CRDT.DotKernel.remove(dot_kernel, value)}
end
Expand Down
12 changes: 6 additions & 6 deletions lib/crdt/delta_awor_set.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ defmodule CRDT.DeltaAWORSet do
}
}
"""
@spec new() :: t
@spec new() :: t()
def new, do: %__MODULE__{}

@doc """
Expand All @@ -48,7 +48,7 @@ defmodule CRDT.DeltaAWORSet do
}
}
"""
@spec add(t, actor, value) :: t
@spec add(t(), actor(), value()) :: t()
def add(%__MODULE__{dot_kernel: dot_kernel, delta: delta}, actor, value) do
{dot_kernel, delta} =
{dot_kernel, delta}
Expand All @@ -75,7 +75,7 @@ defmodule CRDT.DeltaAWORSet do
}
}
"""
@spec remove(t, value) :: t
@spec remove(t(), value()) :: t()
def remove(%__MODULE__{dot_kernel: dot_kernel, delta: delta}, value) do
{dot_kernel, delta} =
{dot_kernel, delta}
Expand All @@ -92,7 +92,7 @@ defmodule CRDT.DeltaAWORSet do
iex> CRDT.DeltaAWORSet.new() |> CRDT.DeltaAWORSet.add(:a, "value") |> CRDT.DeltaAWORSet.value()
["value"]
"""
@spec value(t) :: list
@spec value(t()) :: list()
def value(%__MODULE__{dot_kernel: dot_kernel}) do
CRDT.DotKernel.values(dot_kernel)
end
Expand All @@ -119,7 +119,7 @@ defmodule CRDT.DeltaAWORSet do
}
}
"""
@spec merge(t, t) :: t
@spec merge(t(), t()) :: t()
def merge(
%__MODULE__{dot_kernel: dot_kernel_a, delta: delta_a},
%__MODULE__{dot_kernel: dot_kernel_b, delta: delta_b}
Expand Down Expand Up @@ -151,7 +151,7 @@ defmodule CRDT.DeltaAWORSet do
}
}
"""
@spec merge_delta(t, CRDT.DotKernel.t()) :: t
@spec merge_delta(t(), CRDT.DotKernel.t()) :: t()
def merge_delta(%__MODULE__{dot_kernel: dot_kernel_a, delta: delta_a}, delta) do
%__MODULE__{
dot_kernel: CRDT.DotKernel.merge(dot_kernel_a, delta),
Expand Down
12 changes: 6 additions & 6 deletions lib/crdt/dot_context.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ defmodule CRDT.DotContext do
iex> CRDT.DotContext.new()
%CRDT.DotContext{version_vector: %{}, dot_cloud: []}
"""
@spec new() :: t
@spec new() :: t()
def new, do: %__MODULE__{}

@doc """
Expand All @@ -31,7 +31,7 @@ defmodule CRDT.DotContext do
iex> CRDT.DotContext.new() |> CRDT.DotContext.contains?({:a, 1})
false
"""
@spec contains?(t, dot) :: boolean
@spec contains?(t(), dot()) :: boolean
def contains?(
%__MODULE__{version_vector: version_vector, dot_cloud: dot_cloud},
{actor, version} = dot
Expand All @@ -53,7 +53,7 @@ defmodule CRDT.DotContext do
iex> CRDT.DotContext.new() |> CRDT.DotContext.next_dot(:a)
{{:a, 1}, %CRDT.DotContext{version_vector: %{a: 1}, dot_cloud: []}}
"""
@spec next_dot(t, actor) :: {dot, t}
@spec next_dot(t(), actor()) :: {dot(), t()}
def next_dot(%__MODULE__{version_vector: version_vector} = dot_context, actor) do
version = Map.get(version_vector, actor, 0) + 1

Expand All @@ -74,7 +74,7 @@ defmodule CRDT.DotContext do
iex> CRDT.DotContext.new() |> CRDT.DotContext.add({:a, 1})
%CRDT.DotContext{version_vector: %{}, dot_cloud: [{:a, 1}]}
"""
@spec add(t, dot) :: t
@spec add(t(), dot()) :: t()
def add(%__MODULE__{dot_cloud: dot_cloud} = dot_context, dot) do
%{dot_context | dot_cloud: [dot | dot_cloud]}
end
Expand All @@ -94,7 +94,7 @@ defmodule CRDT.DotContext do
...> |> CRDT.DotContext.compress()
%CRDT.DotContext{version_vector: %{a: 3}, dot_cloud: [{:b, 2}, {:a, 5}]}
"""
@spec compress(t) :: t
@spec compress(t()) :: t()
def compress(%__MODULE__{version_vector: version_vector, dot_cloud: dot_cloud}) do
{version_vector, dot_cloud} =
for {actor, version} = dot <- Enum.sort(dot_cloud), reduce: {version_vector, []} do
Expand Down Expand Up @@ -135,7 +135,7 @@ defmodule CRDT.DotContext do
...> )
%CRDT.DotContext{version_vector: %{a: 5}, dot_cloud: [{:b, 2}, {:a, 7}]}
"""
@spec merge(t, t) :: t
@spec merge(t(), t()) :: t()
def merge(
%__MODULE__{version_vector: version_vector_a, dot_cloud: dot_cloud_a},
%__MODULE__{version_vector: version_vector_b, dot_cloud: dot_cloud_b}
Expand Down
14 changes: 7 additions & 7 deletions lib/crdt/dot_kernel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ defmodule CRDT.DotKernel do
entries: %{}
}
"""
@spec new() :: t
@spec new() :: t()
def new, do: %__MODULE__{}

@doc """
Expand Down Expand Up @@ -53,7 +53,7 @@ defmodule CRDT.DotKernel do
}
}
"""
@spec add(t, actor, value) :: t
@spec add(t(), actor(), value()) :: t()
def add(%__MODULE__{dot_context: dot_context, entries: entries}, actor, value) do
{dot, dot_context} = CRDT.DotContext.next_dot(dot_context, actor)

Expand All @@ -63,7 +63,7 @@ defmodule CRDT.DotKernel do
}
end

@spec add({t, t}, actor, value) :: {t, t}
@spec add({t(), t()}, actor(), value()) :: {t(), t()}
def add(
{
%__MODULE__{dot_context: dot_context, entries: entries},
Expand Down Expand Up @@ -115,7 +115,7 @@ defmodule CRDT.DotKernel do
}
}
"""
@spec remove(t, value) :: t
@spec remove(t(), value()) :: t()
def remove(%__MODULE__{entries: entries} = dot_kernel, value) do
entries =
for {dot, entry_value} <- entries, entry_value == value, reduce: entries do
Expand All @@ -128,7 +128,7 @@ defmodule CRDT.DotKernel do
%__MODULE__{dot_kernel | entries: entries}
end

@spec remove({t, t}, value) :: {t, t}
@spec remove({t(), t()}, value()) :: {t(), t()}
def remove(
{
%__MODULE__{entries: entries} = dot_kernel,
Expand Down Expand Up @@ -164,7 +164,7 @@ defmodule CRDT.DotKernel do
["value"]

"""
@spec values(t) :: list
@spec values(t()) :: list()
def values(%__MODULE__{entries: entries}) do
Map.values(entries)
end
Expand All @@ -188,7 +188,7 @@ defmodule CRDT.DotKernel do
entries: %{{:a, 1} => "value1"}
}
"""
@spec merge(t, t) :: t
@spec merge(t(), t()) :: t()
def merge(
%__MODULE__{dot_context: dot_context_a, entries: entries_a},
%__MODULE__{dot_context: dot_context_b, entries: entries_b}
Expand Down
6 changes: 3 additions & 3 deletions lib/crdt/g_counter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ defmodule CRDT.GCounter do
iex> CRDT.GCounter.new()
%CRDT.GCounter{value: %{}}
"""
@spec new() :: t
@spec new() :: t()
def new, do: %__MODULE__{}

@doc """
Expand All @@ -28,7 +28,7 @@ defmodule CRDT.GCounter do
iex> CRDT.GCounter.new(a: 1, b: 2)
%CRDT.GCounter{value: %{a: 1, b: 2}}
"""
@spec new([{actor, non_neg_integer}]) :: t
@spec new([{actor(), non_neg_integer()}]) :: t()
def new(values) do
%__MODULE__{value: Map.new(values)}
end
Expand All @@ -43,7 +43,7 @@ defmodule CRDT.GCounter do
...> |> CRDT.GCounter.inc(:b, 2)
%CRDT.GCounter{value: %{a: 1, b: 2}}
"""
@spec inc(t, actor, non_neg_integer) :: t
@spec inc(t(), actor(), non_neg_integer()) :: t()
def inc(%__MODULE__{value: value}, actor, amount \\ 1) do
%__MODULE__{value: Map.update(value, actor, amount, &(&1 + amount))}
end
Expand Down
Loading