Malachi. Cluster. PolicyRegistry
(malachi v0.22.7)
View Source
The pure state of the cluster's storage policies: the named definitions an administrator writes,
replicated by Malachi.Cluster.PolicyMachine over a dedicated ra cluster.
Why they do not live in the metadata
A policy is an administrative object bound to topics, not state a vnode owns. Malachi used to keep the
definitions inside each vnode's Malachi.Metadata, which had a defect built into it: a topic moving
between vnodes carries the policy NAME it points at, and the definition stayed behind, so after a vnode
split the topic silently fell back to the global retention and lost its placement spread. One
definition for the cluster removes that by construction rather than by copying it around.
What stays in Malachi.Metadata is the binding, {:bind_topic_policy, topic, name}: which policy a
topic points at is a fact about that topic and travels with it.
A definition is validated by Malachi.Cluster.Policy before it is stored, so every replica agrees on
what a policy is. Pure: no clock, no config.
Summary
Functions
Every definition, as a map from name to policy. What a retention sweep resolves against once per pass.
Applies a command at the group's effective machine version, returning {new_state, reply}.
Every command shape, mapped to the machine version that introduced it (see Malachi.Cluster.MachineVersion).
The policy named name, or nil when no such policy is defined.
An empty registry.
Types
@type command() :: {:define_policy, Malachi.Cluster.Policy.name(), Malachi.Cluster.Policy.t()} | {:delete_policy, Malachi.Cluster.Policy.name()}
@type t() :: %Malachi.Cluster.PolicyRegistry{ policies: %{ required(Malachi.Cluster.Policy.name()) => Malachi.Cluster.Policy.t() } }
Functions
@spec all(t()) :: %{ required(Malachi.Cluster.Policy.name()) => Malachi.Cluster.Policy.t() }
Every definition, as a map from name to policy. What a retention sweep resolves against once per pass.
@spec apply(t(), command(), non_neg_integer()) :: {t(), term()}
Applies a command at the group's effective machine version, returning {new_state, reply}.
:define_policy is last-write-wins on a name, which is what an administrator editing a policy means.
The definition is validated against the fields version admits (Malachi.Cluster.Policy.validate/3),
never against what this build knows: version is replicated, so every member reaches the same answer
while some still run older code. A field above it is refused as
{:unsupported_policy_field, name, since, version}, anything else that is not a policy as
:invalid_policy.
:delete_policy is idempotent and does not look for topics pointing at the name: a topic whose
policy is undefined holds its data (see Malachi.Cluster.Retention.effective/4), and making the delete
conditional on a scan of every vnode's topics is not something this registry can do. The admin facade
checks for bound topics before it submits one (Malachi.Policies.delete/3).
Every command shape, mapped to the machine version that introduced it (see Malachi.Cluster.MachineVersion).
@spec get(t(), Malachi.Cluster.Policy.name()) :: Malachi.Cluster.Policy.t() | nil
The policy named name, or nil when no such policy is defined.
@spec new() :: t()
An empty registry.