macula_cluster (macula v11.1.0)
View SourceCluster management utilities for Macula platform.
This module provides cluster infrastructure functions that other applications (like bc_gitops) can delegate to when running on the Macula platform.
Distribution
The ensure_distributed/0 function ensures the node is running in distributed mode. If not already distributed, it starts distribution with a generated node name.
Cookie Management
macula sets no distribution cookie, and reads or writes no cookie file. A node's cookie is its release's own configuration: -setcookie, or the owner-only .erlang.cookie that OTP's auth reads in the node's HOME and
Node Monitoring
The monitor_nodes/0 and unmonitor_nodes/0 functions wrap net_kernel:monitor_nodes/1 for subscribing to nodeup/nodedown messages.
bc_gitops Integration
When bc_gitops is running on the Macula platform, it detects these exports and delegates clustering operations here. This allows Macula to own cluster infrastructure while bc_gitops remains usable standalone.
Summary
Functions
Ensure this node is running in distributed mode.
Get the short hostname of this machine.
Check if auto-clustering is currently active.
Check if this node is running in distributed mode.
Subscribe to node up/down events.
Get list of connected cluster nodes.
Start automatic cluster formation with default options.
Start automatic cluster formation with options.
Stop automatic cluster formation.
Unsubscribe from node up/down events.
Functions
-spec ensure_distributed() -> ok | {error, term()}.
Ensure this node is running in distributed mode.
If the node is already distributed, returns ok immediately. Otherwise, starts distribution with a generated node name in the format macula_host@hostname.
Examples:
ok = macula_cluster:ensure_distributed().
-spec get_hostname() -> string().
Get the short hostname of this machine.
Examples:
"myhost" = macula_cluster:get_hostname().
-spec is_clustered() -> boolean().
Check if auto-clustering is currently active.
Returns true if the gossip or static strategy is running.
-spec is_distributed() -> boolean().
Check if this node is running in distributed mode.
-spec monitor_nodes() -> ok.
Subscribe to node up/down events.
After calling this function, the calling process will receive {nodeup, Node} and {nodedown, Node} messages when nodes join or leave the cluster.
Examples:
ok = macula_cluster:monitor_nodes().
receive
{nodeup, Node} -> io:format("Node joined: ~p~n", [Node]);
{nodedown, Node} -> io:format("Node left: ~p~n", [Node])
end.
-spec nodes() -> [atom()].
Get list of connected cluster nodes.
Returns all nodes connected to this node via Erlang distribution.
Examples:
Nodes = macula_cluster:nodes().
%% => ['node1@host1', 'node2@host2']
-spec start_cluster() -> ok | {error, term()}.
Start automatic cluster formation with default options.
Uses the static strategy by default, reading nodes from: 1. Application env: {macula, [{cluster_nodes, [Node1, Node2, ...]}]} 2. Environment variable: CLUSTER_NODES (comma-separated)
If no nodes are configured, starts the gossip strategy, which needs a shared secret of at least 32 bytes in MACULA_GOSSIP_SECRET.
Examples:
%% With CLUSTER_NODES env var set
ok = macula_cluster:start_cluster().
%% Or configure in sys.config
{macula, [{cluster_nodes, ['node1@host1', 'node2@host2']}]}
Start automatic cluster formation with options.
Options: - strategy: auto (default), gossip or static. Any other value returns {error, {unknown_strategy, Strategy}} without starting distribution. - nodes: List of node atoms (for static strategy) - reconnect_interval: Milliseconds between reconnect attempts (default 5000) - callback: PID or {Module, Function} to receive cluster events
Gossip options (for gossip strategy): - multicast_addr: IPv4 multicast address (default {230, 1, 1, 251}) - port: UDP port (default 45892) - broadcast_interval: Milliseconds between broadcasts (default 1500) - multicast_ttl: TTL for multicast packets (default 1 = same subnet) - secret: Shared secret of at least 32 bytes, required by gossip unless MACULA_GOSSIP_SECRET holds one. Without it, a start that uses gossip returns {error, {gossip_strategy_failed, secret_required}}.
Strategy selection: - gossip: UDP multicast gossip for zero-config LAN (like libcluster Gossip) - static: Uses a known list of nodes (like libcluster Epmd strategy) - auto: Chooses strategy based on configuration
Examples:
%% Gossip strategy for zero-config LAN discovery (recommended)
ok = macula_cluster:start_cluster(#{
strategy => gossip,
secret => <<"at least 32 bytes of shared secret">>
}).
%% Gossip with custom multicast group
ok = macula_cluster:start_cluster(#{
strategy => gossip,
multicast_addr => {239, 1, 1, 1},
port => 9999,
secret => <<"at least 32 bytes of shared secret">>
}).
%% Static strategy with explicit nodes
ok = macula_cluster:start_cluster(#{
strategy => static,
nodes => ['node1@host1', 'node2@host2']
}).
-spec stop_cluster() -> ok.
Stop automatic cluster formation.
Stops the cluster strategy process and disconnects from managed nodes.
-spec unmonitor_nodes() -> ok.
Unsubscribe from node up/down events.
Stops the calling process from receiving nodeup/nodedown messages.