Mix.install([
  {:erlfdb, "~> 1.0"},
  {:dgen, github: "foundationdb-beam/dgen"}
])

Intro

DGen.Registry is a distributed Elixir process registry that is built to gracefully and automatically handle nodes joining and leaving your cluster.

If you're already running DGen, all you have to do to use the registry is

  1. Ensure your nodes are capable of communication (e.g. VM config, network, cookie)
  2. Add a new child to your supervision tree

As long as you do this, DGen.Registry will take care of clustering the Elixir VMs with each other and will ensure that the dataset they share (namely process registrations) is consistent across the cluster.

Nodes can join and leave at your will. DGen.Registry keeps everything up-to-date.

Reminder: The DGen project is a set of OTP-like utilities that inherit their distributed consensus from a backend database. As of the time of writing, the single supported backend is FoundationDB. Thus, DGen.Registry requires that your application connects to a running FoundationDB cluster.

What this document covers

This document, an interactive Livebook, covers the "Getting Started" of DGen.Registry, including how to register processes and metadata and how to query them.

For a discussion of the consistency guarantees of DGen.Registry, please see the :dgen_registry Design Doc

Getting Started

tenant = :dgen_erlfdb.sandbox_open("lb", "acme_corp")
DGen.Registry.start_link(:my_registry, tenant)
defmodule Player do
  use GenServer

  def start_link(name) do
    GenServer.start_link(__MODULE__, %{}, name: {:via, DGen.Registry, {:my_registry, name}})
  end

  def move_to_room(name, room) do
    :dgen_registry.set_metadata(
      {:my_registry, name},
      %{index: %{room: room}, data: %{}}
    )
  end

  @impl true
  def init(_) do
    {:ok, %{}}
  end
end

defmodule Room do
  def list_players(room) do
    :dgen_registry.query(:my_registry, %{room: room})
    |> Enum.map(fn %{name: name, pid: pid} -> {name, pid} end)
  end
end
Player.start_link("alice")
GenServer.whereis({:via, DGen.Registry, {:my_registry, "alice"}})
Player.move_to_room("alice", 37)
Room.list_players(37)
Player.start_link("bob")
Player.move_to_room("bob", 37)
Room.list_players(37)
GenServer.stop({:via, DGen.Registry, {:my_registry, "bob"}})
Room.list_players(37)