macula_cluster (macula v11.1.0)

View Source

Cluster 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.

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

ensure_distributed()

-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().

get_hostname()

-spec get_hostname() -> string().

Get the short hostname of this machine.

Examples:

  "myhost" = macula_cluster:get_hostname().

is_clustered()

-spec is_clustered() -> boolean().

Check if auto-clustering is currently active.

Returns true if the gossip or static strategy is running.

is_distributed()

-spec is_distributed() -> boolean().

Check if this node is running in distributed mode.

monitor_nodes()

-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.

nodes()

-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']

start_cluster()

-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_cluster(Opts)

-spec start_cluster(map()) -> ok | {error, term()}.

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']
  }).

stop_cluster()

-spec stop_cluster() -> ok.

Stop automatic cluster formation.

Stops the cluster strategy process and disconnects from managed nodes.

unmonitor_nodes()

-spec unmonitor_nodes() -> ok.

Unsubscribe from node up/down events.

Stops the calling process from receiving nodeup/nodedown messages.