View Source ProcessHub.Service.Synchronizer (ProcessHub v0.7.0)
The synchronizer service provides API functions for synchronizing process registry data between nodes.
Summary
Functions
Merges a peer's registry rows into the local process registry.
Broadcasts local registry data to the specified target nodes.
Returns {:ok, data} to broadcast, or :suppress.
Withdraws a peer's observations for children its payload does not mention.
Returns the local node's process registry data used for synchronization.
Helper function to trigger interval synchronization.
Functions
@spec append_data(ProcessHub.Hub.t(), %{ required(node()) => [ {ProcessHub.child_spec(), pid(), ProcessHub.child_metadata()} ] }) :: :ok
Merges a peer's registry rows into the local process registry.
The row itself — child spec, caller metadata, and hub bookkeeping — resolves by higher epoch, ties broken by the lexicographically lower authoring node name, so every node converges on the same value in any order and with any number of repetitions. The winner is adopted verbatim: a merge does not author a row and never increments an epoch.
node_pids is not part of that resolution. A payload from node N carries
observations N owns, so only the {N, pid} entry is touched; entries owned by
any other node are left alone.
@spec broadcast_local_registry(ProcessHub.Hub.t(), [node()]) :: :ok
Broadcasts local registry data to the specified target nodes.
Called when new nodes join the cluster to share local process information.
@spec broadcastable_local_data(ProcessHub.Hub.t()) :: {:ok, [{ProcessHub.child_spec(), pid(), ProcessHub.child_metadata()}]} | :suppress
Returns {:ok, data} to broadcast, or :suppress.
A node that has hosted no local child since boot returns an empty
local_sync_data/1; broadcasting it would make peers' detach_data/2 treat
the node as authoritatively empty and wipe its records. We suppress that empty
until the node has hosted a child at least once (latched in storage.misc,
which resets on restart). A node that legitimately drained its children is
already latched, so it still broadcasts its empty and peers reconcile.
@spec detach_data(ProcessHub.Hub.t(), %{ required(node()) => [{ProcessHub.child_spec(), pid()}] }) :: :ok
Withdraws a peer's observations for children its payload does not mention.
Absence is an observation, never an authority: a child missing from node N's
payload drops only the {N, pid} entry. The row survives an emptied node list —
it becomes a candidate for the next orphan reconcile round instead of being
deleted, so a peer reporting a partial or empty registry can never erase durable
state on any other node.
@spec local_sync_data(ProcessHub.Hub.t()) :: [ {ProcessHub.child_spec(), pid(), ProcessHub.child_metadata()} ]
Returns the local node's process registry data used for synchronization.
Carries the children bound locally, each reported with the pid this node observes — a bound row travels with its holder. Stop knowledge does not travel here: for declared children it lives in the declared list, and unbound rows are deliberately not carried, because peers cannot act on them.
Helper function to trigger interval synchronization.
The system will use the configured synchronization strategy.