Malachi.Cluster.LeaseServer (malachi v0.22.7)

View Source

A thin named facade over Malachi.Cluster.RaCluster for the cluster's lease (Malachi.Cluster.LeaseMachine): start the dedicated Raft cluster, submit acquire_or_renew/release commands through the log, and run a consistent (linearizable) query of the lease state. Mirrors MetadataServer; ra must already be running (:ra.start_in/1). This module owns only the lease cluster, not ra's lifecycle.

Until issue #32 this was the one store that formed without resuming first: start/2 called :ra.start_cluster directly, so a returning member could be re-created over its registered uid and come back amnesiac. Going through RaCluster fixes that here by construction.

Commands return {:ok, machine_reply} (the machine reply is {:ok, fence} on grant or {:error, {:held, holder}} on refusal) or {:error, reason} when the cluster is unreachable, the caller (LeaseHolder) distinguishes "refused" from "could not reach", treating the latter as not-renewed.

Summary

Functions

Acquires the lease for candidate (or renews it if already held), for duration_ms. Returns {:ok, {:ok, fence}} on grant, {:ok, {:error, {:held, holder}}} when held by another, or {:error, reason} when the cluster is unreachable.

Stops and deletes the lease's Raft cluster (removing its on-disk state).

The current lease state via a consistent query. The {Function, :identity, []} is ra's required shape for a consistent query (a plain fun is rejected); it returns the machine state unchanged.

Ensures this node participates in the lease cluster (self-join), so a staggered boot converges to a fully-replicated lease. Idempotent and best-effort: it tries to form the cluster if it is not yet formed (start/2, auto-fenced) and to start the local server if it is not running (:ra.start_server). The local node is already a config member (the initial start_cluster lists every node), so starting its server rejoins the existing cluster and ra replicates the lease state to it: recovering a node that was down when the cluster first formed. A no-op once the local server is up. Meant to be called periodically by Malachi.Cluster.LeaseReconciler until the node has joined.

Releases the lease if candidate still holds it at fence (idempotent). Returns {:ok, :ok}.

Starts the lease's Raft cluster named cluster_name across nodes (default the local node) and returns a server_id addressing a real member (the local node when it is one, else the first).

Types

cluster_name()

@type cluster_name() :: atom()

server_id()

@type server_id() :: {cluster_name(), node()}

Functions

acquire_or_renew(server_id, candidate, duration_ms)

@spec acquire_or_renew(server_id(), term(), pos_integer()) ::
  {:ok, Malachi.Cluster.Lease.reply()} | {:error, term()}

Acquires the lease for candidate (or renews it if already held), for duration_ms. Returns {:ok, {:ok, fence}} on grant, {:ok, {:error, {:held, holder}}} when held by another, or {:error, reason} when the cluster is unreachable.

delete(cluster_name)

@spec delete(cluster_name()) :: :ok

Stops and deletes the lease's Raft cluster (removing its on-disk state).

get(server_id)

@spec get(server_id()) :: {:ok, Malachi.Cluster.Lease.t()} | {:error, term()}

The current lease state via a consistent query. The {Function, :identity, []} is ra's required shape for a consistent query (a plain fun is rejected); it returns the machine state unchanged.

reconcile(cluster_name, nodes)

@spec reconcile(cluster_name(), [node()]) :: :ok

Ensures this node participates in the lease cluster (self-join), so a staggered boot converges to a fully-replicated lease. Idempotent and best-effort: it tries to form the cluster if it is not yet formed (start/2, auto-fenced) and to start the local server if it is not running (:ra.start_server). The local node is already a config member (the initial start_cluster lists every node), so starting its server rejoins the existing cluster and ra replicates the lease state to it: recovering a node that was down when the cluster first formed. A no-op once the local server is up. Meant to be called periodically by Malachi.Cluster.LeaseReconciler until the node has joined.

release(server_id, candidate, fence)

@spec release(server_id(), term(), non_neg_integer()) ::
  {:ok, Malachi.Cluster.Lease.reply()} | {:error, term()}

Releases the lease if candidate still holds it at fence (idempotent). Returns {:ok, :ok}.

start(cluster_name, nodes \\ [node()])

@spec start(cluster_name(), [node()]) :: {:ok, server_id()} | {:error, term()}

Starts the lease's Raft cluster named cluster_name across nodes (default the local node) and returns a server_id addressing a real member (the local node when it is one, else the first).