nessie_cluster

An actor that periodically polls DNS for IP addresses and connects to Erlang nodes.

A DNS query is made every interval milliseconds to discover new IPs. Nodes will only be joined if their basename matches the basename of the current node. Nodes running on remote hosts but with different basenames will fail to connect and be ignored.

For all configuration options, see the with_* functions in this module.

Types

The central DNS cluster type.

Use the new function to create a new cluster, and then use the with_* functions to configure it.

pub opaque type DnsCluster

A DNS query to be used to discover ndoes.

pub type DnsQuery {
  DnsQuery(query: String)
  Ignore
}

Constructors

  • DnsQuery(query: String)

    A DNS name to query.

  • Ignore

    Indicate that the cluster should not perform DNS lookups, and therefore not connect to any nodes.

    This is useful when running in a development environment where clustering isn’t necessary.

A simple logger type which should print the message.

pub type Logger =
  fn(LoggerLevel, String) -> Nil
pub type LoggerLevel =
  String
pub opaque type Message
pub type NodeConnectError {
  NodeConnectError(node: Atom, error: ConnectError)
}

Constructors

  • NodeConnectError(node: Atom, error: ConnectError)

    Arguments

    • node

      The nodename@nodeip atom that failed to connect.

    • error

      The error that occurred while trying to connect.

The engine powering DNS lookups and node connections. This is mostly useful for testing; the Resolver returned by default_resolver should be sufficient for most - if not all - uses.

pub type Resolver {
  Resolver(
    basename: fn(Atom) -> Result(String, Nil),
    connect_node: fn(Atom) -> Result(Node, ConnectError),
    list_nodes: fn() -> List(Node),
    lookup: fn(String) -> List(String),
  )
}

Constructors

  • Resolver(
      basename: fn(Atom) -> Result(String, Nil),
      connect_node: fn(Atom) -> Result(Node, ConnectError),
      list_nodes: fn() -> List(Node),
      lookup: fn(String) -> List(String),
    )

    Arguments

    • basename

      Extract the base name of a node (i.e. everything before the @ symbol).

    • connect_node

      Connect to a node by name.

    • list_nodes

      List all visible nodes.

    • lookup

      Perform a DNS lookup, returning a list of IP addresses as strings.

Functions

pub fn default_resolver() -> Resolver

Returns the default resolver which will query for A and AAAA records, and try to connect to Erlang nodes at all of the returned IP addresses.

Most library consumers will never use this function, however it is provided in-case a more complex resolution strategy is desired.

pub fn discover_nodes(
  on subject: Subject(Message),
  timeout_millis timeout: Option(Int),
) -> Result(
  #(List(Node), List(NodeConnectError)),
  CallError(#(List(Node), List(NodeConnectError))),
)

Triggers node discovery manually, returning a tuple containing the list of connected nodes (after doing discovery) and a list of connection errors that occurred, if any.

If no timeout is supplied, this function returns immediately with Ok(#([], [])) after sending a message to trigger node discovery.

This function is only useful for advanced cases - the DNS cluster polls at a regular interval by default, which is typically sufficient.

pub fn has_ran(
  subject: Subject(Message),
  timeout: Int,
) -> Result(Bool, CallError(Bool))

Returns a boolean indicating whether DNS discovery has ran at least once.

Useful for running in a healthcheck to ensure at least 1 DNS discovery cycle has ran.

pub fn new() -> DnsCluster

Create a new DnsCluster for the given query.

Note that the returned DNS cluster does not actually do anything if a query is not provided using with_query.

pub fn start_spec(
  cluster: DnsCluster,
  parent_subject: Option(Subject(Subject(Message))),
) -> Result(Subject(Message), StartError)

Starts an actor which will periodically poll DNS for IP addresses and connect to Erlang nodes.

If the cluster’s query is Ignore, the actor will start successfully, but will not perform any DNS lookups or attempt to connect to any nodes.

pub fn stop(
  subject: Subject(Message),
  timeout: Int,
) -> Result(Nil, CallError(Nil))

Stop the DNS cluster.

This causes the actor to exit normally.

pub fn with_interval(
  for cluster: DnsCluster,
  millis interval: Option(Int),
) -> DnsCluster

Set the interval at which DNS is polled. If None, the cluster will only poll DNS when discover_nodes is called.

Defaults to 5000 milliseconds.

pub fn with_logger(
  for cluster: DnsCluster,
  using logger: fn(String, String) -> Nil,
) -> DnsCluster

Turn logging on or off for the given cluster.

Defaults to a gleam/io.println() call, prepending the log level to the message.

pub fn with_name(
  for cluster: DnsCluster,
  using name: Atom,
) -> DnsCluster

Use a custom name for the process.

The default nessie_cluster name is typically sufficient.

pub fn with_query(
  for cluster: DnsCluster,
  using q: DnsQuery,
) -> DnsCluster

Set the query for the given DNS cluster.

Defaults to Ignore.

pub fn with_resolver(
  for cluster: DnsCluster,
  using resolver: Resolver,
) -> DnsCluster

Set a custom resolver for the given cluster.

For details on the default resolver, see the documentation for the default_resolver function.

Most users will not need to change this, but it can be useful for testing or more advanced use-cases.

Search Document