Malachi. Cluster. Lease
(malachi v0.8.13)
View Source
The pure state of a lease: a fenced, expiring lock that elects a single holder for the
non-idempotent work of rebalancing. It is the deterministic core replicated by LeaseMachine
over a dedicated ra cluster (exactly as Malachi.Metadata sits behind MetadataMachine), so every
replica reaches the same lease state from the same command log.
A candidate acquire_or_renews the lease; it is granted when the lease is free, already held by
that candidate (a renewal), or expired (now >= renew_at + duration_ms). The candidate identity
must be a non-nil term (nil is the free-lease sentinel); in practice it is the node. Time is supplied by the
caller: LeaseMachine passes the ra leader's system_time - and never read inside apply/3: reading
a wall clock there would be non-deterministic and break Raft. So a single clock (the lease cluster's
current leader) decides expiry, avoiding the cross-node clock skew a client-supplied time would carry.
fence is a monotonic fencing token: it advances only when the holder changes (a renewal keeps
it). A holder carries its token into the work it fences; if the token has since advanced, a stale
ex-holder's writes can be rejected: the guard against two simultaneous holders.
Summary
Functions
Applies a lease command at time now (epoch ms, from the ra leader's system_time). Returns
{new_state, reply}. Deterministic given now.
The current holder, or nil when the lease is free.
A free lease (no holder, fence 0).
Types
@type command() :: {:acquire_or_renew, holder :: term(), duration_ms :: pos_integer()} | {:release, holder :: term(), fence :: non_neg_integer()}
@type reply() :: {:ok, fence :: non_neg_integer()} | {:error, {:held, holder :: term()}} | :ok
@type t() :: %Malachi.Cluster.Lease{ duration_ms: pos_integer() | nil, fence: non_neg_integer(), holder: term() | nil, renew_at: integer() | nil }
Functions
Applies a lease command at time now (epoch ms, from the ra leader's system_time). Returns
{new_state, reply}. Deterministic given now.
The current holder, or nil when the lease is free.
@spec new() :: t()
A free lease (no holder, fence 0).