Ferricstore.Raft.Cluster (ferricstore v0.3.1)

Copy Markdown View Source

Manages the ra Raft cluster for FerricStore shards.

Each shard is an independent Raft group with its own leader. In single-node mode (development, testing), each group has exactly one member -- self quorum.

This module provides functions to:

  • Start the ra system
  • Start individual shard ra servers
  • Build ra server IDs and configurations

Deployment topology (per spec section 2.6)

Single node: each shard's Raft group has one member. Writes are durable after local log append + fsync. No network round trip needed.

Three-node cluster: each shard's Raft group has three members. Writes require quorum (2 of 3) acknowledgement before commit.

Summary

Functions

Adds a node to an existing shard's Raft group.

Returns the current members and leader for a shard's Raft group.

Removes a node from a shard's Raft group.

Returns the ra server ID for a shard.

Returns the ra server ID for a shard on a specific node.

Starts the ra system for FerricStore.

Stops and deletes the ra server for a shard.

Returns the ra system name used by FerricStore.

Transfers leadership of a shard to a specific node.

Functions

add_member(shard_index, node, membership \\ :voter)

@spec add_member(non_neg_integer(), node(), atom()) :: :ok | {:error, term()}

Adds a node to an existing shard's Raft group.

The membership determines the node's role:

  • :voter — full quorum member (default)
  • :promotable — receives replication, can be promoted to voter
  • :non_voter — permanent read-only, never promoted

Parameters

  • shard_index — zero-based shard index
  • node — the Erlang node to add
  • membership:voter, :promotable, or :non_voter (default: :voter)

join_shard_server(shard_index, shard_data_path, active_file_id, active_file_path, ets, cluster_members, opts \\ [])

@spec join_shard_server(
  non_neg_integer(),
  binary(),
  non_neg_integer(),
  binary(),
  atom(),
  [node()],
  keyword()
) :: :ok | {:error, term()}

Starts a ra server that joins an existing Raft group as a follower.

Unlike start_shard_server/6 which may create a new single-node group, this function configures initial_members with the provided cluster members so ra knows to join the existing group. Used when a new node joins an already-running cluster after data sync.

members(shard_index)

@spec members(non_neg_integer()) :: {:ok, list(), term()} | {:error, term()}

Returns the current members and leader for a shard's Raft group.

remove_member(shard_index, node)

@spec remove_member(non_neg_integer(), node()) :: :ok | {:error, term()}

Removes a node from a shard's Raft group.

shard_server_id(shard_index)

@spec shard_server_id(non_neg_integer()) :: :ra.server_id()

Returns the ra server ID for a shard.

The server ID is a {name, node()} tuple as required by ra.

Examples

iex> Ferricstore.Raft.Cluster.shard_server_id(0)
{:"ferricstore_shard_0", node()}

shard_server_id_on(shard_index, node)

@spec shard_server_id_on(non_neg_integer(), node()) :: :ra.server_id()

Returns the ra server ID for a shard on a specific node.

start_shard_server(shard_index, shard_data_path, active_file_id, active_file_path, ets, opts \\ [])

@spec start_shard_server(
  non_neg_integer(),
  binary(),
  non_neg_integer(),
  binary(),
  atom(),
  keyword()
) ::
  :ok | {:error, term()}

Starts a ra server for a single shard.

In single-node mode, creates a self-quorum Raft group. In cluster mode, uses the configured cluster_nodes as initial_members so all nodes form a single Raft group per shard.

The membership option controls this node's role in the group:

  • :voter — full quorum member (default)
  • :promotable — receives replication, can be promoted
  • :non_voter — permanent read-only

Parameters

  • shard_index -- zero-based shard index
  • shard_data_path -- path to shard's Bitcask data directory
  • active_file_id -- current active log file ID
  • active_file_path -- path to current active log file
  • ets -- ETS table name (already created)

Returns

  • :ok on success
  • {:error, reason} on failure

start_system(data_dir)

@spec start_system(binary()) :: :ok | {:error, term()}

Starts the ra system for FerricStore.

Must be called before any ra servers are started. The data directory for ra's WAL and segment files is placed under data_dir/ra.

Parameters

  • data_dir -- base data directory for FerricStore

stop_shard_server(shard_index)

@spec stop_shard_server(non_neg_integer()) :: :ok | {:error, term()}

Stops and deletes the ra server for a shard.

Used during shard restarts and in test cleanup.

Parameters

  • shard_index -- zero-based shard index

system_name()

@spec system_name() :: atom()

Returns the ra system name used by FerricStore.

transfer_leadership(shard_index, target_node)

@spec transfer_leadership(non_neg_integer(), node()) :: :ok | {:error, term()}

Transfers leadership of a shard to a specific node.