Sagents.Horde.MembershipManager (Sagents v0.9.0)
Copy MarkdownKeeps Horde cluster membership scoped to the nodes that actually run
Sagents.Supervisor, and keeps it current as nodes come and go.
This is the membership mechanism behind:
config :sagents, :distribution, :horde
config :sagents, :horde, members: :participationWhy this exists
Horde's built-in members: :auto derives membership from
Node.list([:visible, :this]) — every connected BEAM node, regardless of
whether it runs Horde. In a cluster that meshes multiple service roles into
one Erlang cluster, that pulls unrelated nodes into the Sagents Horde cluster:
it bloats the DeltaCrdt sync fan-out (a cause of registration timeouts) and,
for membership added but never reporting :alive, leaves dead entries that
are never pruned.
Membership here is instead derived from participation: every node that
starts Sagents.Supervisor joins an OTP :pg group, and this process sets
Horde's members to exactly the nodes in that group. Because a node runs
Sagents.Supervisor only where the host application chose to (e.g. gated to a
:web role), "nodes running Sagents" is "agent-hosting nodes" — no
node-name predicate required. :pg removes a node's entry automatically on
:nodedown, so dead nodes are pruned without any extra wiring.
What it manages
On startup and on every :pg join/leave it calls Horde.Cluster.set_members/2
on all three Sagents Horde instances so they stay consistent:
It is started automatically by Sagents.Supervisor (together with its :pg
scope) when members: :participation is configured; you do not start it
yourself.
Partitioning
When config :sagents, :horde, partition: <value> is set, the :pg group is
keyed by that partition ({:sagents_members, value}). A node only joins and
monitors its own partition's group, so membership is isolated per partition —
e.g. nodes in one Fly.io region never become members of another region's Horde
cluster, even when all nodes share one connected BEAM cluster.
Summary
Functions
Returns a specification to start this module under a supervisor.
The :pg group joined by each participating node.
The :pg group for a given partition (nil => unpartitioned base group).
The Horde clusters this manager keeps membership-consistent.
Child spec for the :pg scope this manager relies on.
The :pg scope used for participation tracking.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
The :pg group joined by each participating node.
Keyed by the configured partition (Sagents.Horde.ClusterConfig.partition/0)
so nodes only cluster with same-partition peers. Unpartitioned membership uses
the base group atom.
The :pg group for a given partition (nil => unpartitioned base group).
The Horde clusters this manager keeps membership-consistent.
Child spec for the :pg scope this manager relies on.
Sagents.Supervisor starts this before the manager so the scope is
available when the manager joins and monitors it.
The :pg scope used for participation tracking.