OTP-compatible process registry implementing the {via, dgen_registry, {RegistryName, LogicalName}} contract.
Standard OTP processes (gen_server, gen_statem, gen_event, etc.) can be registered
and addressed by name across an Erlang cluster.
This module implements the four-function contract required for OTP via tuples:
register_name/2— consistent write through the leaderunregister_name/1— consistent delete through the leaderwhereis_name/1— snapshot read from the local member's mapsend/2— routes a message to a named process
Name terms
Every via name is a two-tuple {RegistryName, LogicalName} where
RegistryName identifies which registry to use (the one started with
start_link/2), and LogicalName is any term meaningful to the
application (atom, binary, tuple, …).
Example
{ok, _} = dgen_registry:start_link(my_registry, Tenant),
%% Start a gen_server registered in the dgen registry
gen_server:start_link({via, dgen_registry, {my_registry, user_service}},
my_server, [], []),
%% Call it from anywhere on the cluster
gen_server:call({via, dgen_registry, {my_registry, user_service}}, ping).Consistency model
All writes (register_name, unregister_name) and consistent reads
(whereis_name_consistent) go through the elected leader member process.
The leader is the single writer for the name table.
whereis_name/1 (used by the OTP via-tuple machinery) is a snapshot read
served from the local member's in-memory map — no network hop, no backend
round-trip. This map is kept in sync by one-way replication casts from
the leader. There is therefore a short window after registration where a
remote node's whereis_name/1 may still return undefined; this is the
same eventual-consistency trade-off as gproc global mode.
Leadership
The elected leader is the member process on the Erlang node that most recently committed a backend transaction for the elector queue — i.e., whoever wins the backend consensus. When leadership changes, the elector sets a distributed lock so all elector consumers pause while replication paths are reconfigured. The new leader broadcasts a name snapshot to all followers on assumption.
Auto-unregistration
The leader monitors every registered Pid. When a monitored process exits,
the leader removes the entry and propagates {name_unregistered} to all
follower members.
Summary
Functions
Returns the registered name of the elector process for the given registry name.
Returns the current leader epoch. Increments each time a new leader is elected.
Returns the current leader member id, or undefined if no leader is elected.
Returns the list of all current member ids in the registry.
Returns the registered name of the member process for the given registry name.
Registers Pid under {RegistryName, LogicalName}.
Sends Msg to the process registered as Name, returning the Pid.
Starts the registry supervisor registered as Name.
Starts the registry supervisor registered as SupName, using Name as the registry name.
Removes the registration for {RegistryName, LogicalName}.
Snapshot read — served from the local member's in-memory map.
Consistent read routed through the leader.
Functions
Returns the registered name of the elector process for the given registry name.
-spec get_epoch(Name :: atom()) -> non_neg_integer().
Returns the current leader epoch. Increments each time a new leader is elected.
-spec get_leader(Name :: atom()) -> dgen_registry_elector:member_id() | undefined.
Returns the current leader member id, or undefined if no leader is elected.
-spec get_members(Name :: atom()) -> [dgen_registry_elector:member_id()].
Returns the list of all current member ids in the registry.
Returns the registered name of the member process for the given registry name.
Registers Pid under {RegistryName, LogicalName}.
Routes through the local member, which forwards to the leader if needed.
Returns yes on success, no if the name is already taken or no leader
is currently elected.
Sends Msg to the process registered as Name, returning the Pid.
Exits with reason {badarg, {Name, Msg}} if the name is not registered.
Called internally by gen_server/gen_event for {via, …} routing.
-spec start_link(Name :: atom(), Tenant :: dgen_backend:tenant()) -> supervisor:startlink_ret().
Starts the registry supervisor registered as Name.
-spec start_link(SupName :: atom(), Name :: atom(), Tenant :: dgen_backend:tenant()) -> supervisor:startlink_ret().
Starts the registry supervisor registered as SupName, using Name as the registry name.
Removes the registration for {RegistryName, LogicalName}.
Fire-and-forget: routes through the local member, which forwards to the leader. The local member also removes the entry from its own map immediately so snapshot reads on this node are consistent right away.
Snapshot read — served from the local member's in-memory map.
Never blocks on the leader or the backend. May be slightly stale on follower nodes in the brief window between a remote registration and the replication cast arriving.
Consistent read routed through the leader.
Returns the authoritative Pid for LogicalName, or undefined if not
registered. More expensive than whereis_name/1 but never stale.