lib/pistis/pod/raft.ex

defmodule Pistis.Pod.Raft do
  alias Pistis.Cluster.Manager
  alias Pistis.Pod.MachineWrapper
  use Pistis.Core.Journal

  @raft_cluster_name :pistis

  @spec cluster_name :: :pistis
  @spec start_raft_cluster(keyword(atom)) :: any

  def cluster_name, do: @raft_cluster_name

  def start_raft_cluster([]) do
    raise RuntimeError, message: "No pistis cluster found -- did you forget to configure your network cluster?"
  end

  def start_raft_cluster(nodes) do
    :ra.start_cluster(:default, cluster_name(), MachineWrapper.machine_spec(), nodes)
    |> collect_raft_members()
  end

  def cluster_members() do
    {@raft_cluster_name, pod_address} = Manager.leader_node()
    cluster_members(pod_address)
  end

  def cluster_members(pod_address), do: :ra.members({cluster_name(), pod_address})

  defp collect_raft_members({:ok, started_servers, failed_servers}) do
    {_, pod_address} = List.first(started_servers)
    {_, members, leader} = cluster_members(pod_address)
    {members, failed_servers, leader}
  end

  def to_server_id(node_address), do: {cluster_name(), node_address}

  def dynamic_add({_, pod_address}) do
    :ra.add_member(Manager.leader_node(), to_server_id(pod_address))
    :ra.start_server(
      :default,
      cluster_name(),
      to_server_id(pod_address),
      MachineWrapper.machine_spec(),
      [Manager.leader_node()]
    )
  end
end