Horde has the helpful NodeListener genserver that I've been copy-pasting into toy projects where I'm playing with DeltaCrdt. My approach to libraries built on top of DeltaCrdt has been to start the DeltaCrdt process under a supervisor, with a downstream child that bootstraps node membership. It'd be nice to have an optional NodeListener baked into DeltaCrdt - or even a setup like mine that use a supervisor.
Here's a ReplicatedMap implementation I came up with:
defmodule ReplicatedMap do
use Supervisor
alias ReplicatedMap.{NodeWatcher}
def start_link(opts) do
opts = Keyword.put_new(opts, :name, __MODULE__)
Supervisor.start_link(__MODULE__, opts, name: :"#{opts[:name]}.Supervisor")
end
def init(opts) do
name = opts[:name]
members = opts[:members] || :auto
children = [
{DeltaCrdt, [name: name, crdt: DeltaCrdt.AWLWWMap]},
with_members(members, name)
]
# Restart the node watcher when the ReplicatedMap crashes
# so that node membership is properly resync'd w/ the DeltaCrdt.
Supervisor.init(children, strategy: :rest_for_one)
end
@spec set_members(map :: module(), members :: [GenServer.server()])
def set_members(map, members) when is_list(members) do
DeltaCrdt.set_neighbours(map, members)
end
@spec put(map :: module(), key :: any(), value :: any()) :: module()
def put(map \\ __MODULE__, key, value) do
DeltaCrdt.put(map, key, value)
end
@spec delete(map :: module(), key :: any()) :: module()
def delete(map \\ __MODULE__, key) do
DeltaCrdt.delete(map, key)
end
@spec drop(map :: module(), keys :: [any()]) :: module()
def drop(map \\ __MODULE__, keys) when is_list(keys) do
DeltaCrdt.drop(map, keys)
end
@spec get(map :: module(), key :: any()) :: nil | any()
def get(map \\ __MODULE__, key) do
case DeltaCrdt.read(map, [key]) do
%{^key => val} -> val
_ -> nil
end
end
defp with_members(:auto, crdt_name) do
{NodeWatcher, [name: :"#{crdt_name}.NodeWatcher", crdt_name: crdt_name]}
end
defp with_members(members, crdt_name) when is_list(members) do
{Task, fn -> DeltaCrdt.set_neighbours(crdt_name, members) end}
end
end
This library has been so fun to play with, and I use it to show off "the power of Elixir/Erlang" whenever I have the chance.
Horde has the helpful
NodeListener
genserver that I've been copy-pasting into toy projects where I'm playing with DeltaCrdt. My approach to libraries built on top of DeltaCrdt has been to start theDeltaCrdt
process under a supervisor, with a downstream child that bootstraps node membership. It'd be nice to have an optionalNodeListener
baked intoDeltaCrdt
- or even a setup like mine that use a supervisor.Here's a ReplicatedMap implementation I came up with:
This library has been so fun to play with, and I use it to show off "the power of Elixir/Erlang" whenever I have the chance.