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

Link to this function

append_data(hub, remote_data)

View Source
@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.

Link to this function

broadcast_local_registry(state, target_nodes)

View Source
@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.

Link to this function

broadcastable_local_data(hub)

View Source
@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.

Link to this function

detach_data(hub, remote_children)

View Source
@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.

Link to this function

exec_interval_sync(hub_id, strategy, sync_data, remote_node)

View Source
@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.