lattice_core/version_vector
A version vector for tracking causal ordering between replicas.
Each replica has a logical clock (monotonically increasing integer). Version vectors enable detecting whether two states are causally ordered (one happened before the other) or concurrent (neither dominates). Merge takes the pairwise maximum of all clocks.
Example
import lattice_core/replica_id
import lattice_core/version_vector
let node_a = replica_id.new("node-a")
let node_b = replica_id.new("node-b")
let a = version_vector.new()
|> version_vector.increment(node_a)
|> version_vector.increment(node_a)
let b = version_vector.new()
|> version_vector.increment(node_b)
version_vector.compare(a, b) // -> Concurrent
Types
The causal ordering relationship between two version vectors.
Before: the first vector happened before the second (all clocks <=, at least one strictly <)After: the first vector happened after the second (all clocks >=, at least one strictly >)Concurrent: neither dominates — the states diverged; at least one clock is strictly greater in each directionEqual: both vectors have identical clocks for all replicas
pub type Order {
Before
After
Concurrent
Equal
}
Constructors
-
Before -
After -
Concurrent -
Equal
A version vector tracking logical clocks for each replica.
Internally holds a dictionary from replica ID to clock value. The type is
opaque: use new, increment, get, compare, and merge to interact
with it. Serialization helpers to_dict and from_dict are provided for
JSON encoding and decoding.
pub opaque type VersionVector
Values
pub fn compare(a: VersionVector, b: VersionVector) -> Order
Compare two version vectors and return their causal ordering.
Returns Equal if all clocks match, Before if a is strictly dominated
by b, After if a strictly dominates b, or Concurrent if neither
dominates the other.
pub fn decoder() -> decode.Decoder(VersionVector)
A JSON decoder for VersionVector values.
Decodes the self-describing envelope format produced by to_json.
Useful as a building block in from_json decoders when a VersionVector
is embedded inline within another JSON structure.
pub fn dominates(a: VersionVector, b: VersionVector) -> Bool
Check whether version vector a dominates b.
Returns True when every clock in a is greater than or equal to the
corresponding clock in b. Equivalently, compare(a, b) is Equal or
After.
pub fn from_dict(
d: dict.Dict(replica_id.ReplicaId, Int),
) -> VersionVector
Construct a VersionVector from a raw clock dictionary.
Creates a version vector from a Dict(ReplicaId, Int) mapping replica IDs
to clock values. Useful for deserialization or constructing a version
vector from external data. Prefer new and increment for most use
cases.
pub fn from_json(
json_string: String,
) -> Result(VersionVector, json.DecodeError)
Decode a VersionVector from a JSON string produced by to_json.
Returns Ok(VersionVector) on success, or Error(json.DecodeError) if
the input is not a valid version-vector JSON envelope.
pub fn get(
vv: VersionVector,
replica_id: replica_id.ReplicaId,
) -> Int
Get the clock value for a specific replica.
Returns 0 if replica_id has not been seen (missing entries default
to zero, consistent with the version vector semantics).
pub fn increment(
vv: VersionVector,
replica_id: replica_id.ReplicaId,
) -> VersionVector
Increment the clock for a specific replica.
Returns a new version vector with replica_id’s clock increased by one.
This is the standard way to record a new event at replica_id.
pub fn is_empty(vv: VersionVector) -> Bool
Check whether a version vector is empty (has no clock entries).
pub fn merge(a: VersionVector, b: VersionVector) -> VersionVector
Merge two version vectors using pairwise maximum.
For each replica, the merged clock is the maximum of the two inputs. This operation is commutative, associative, and idempotent.
pub fn new() -> VersionVector
Create a new empty version vector.
All replica clocks start at zero (missing entries are treated as zero).
pub fn set_max(
vv: VersionVector,
replica_id: replica_id.ReplicaId,
value: Int,
) -> VersionVector
Set the clock for a replica to the maximum of the current value and value.
If the replica has no entry, value is used. This avoids round-tripping
through to_dict/from_dict when building a version vector incrementally.
pub fn to_dict(
vv: VersionVector,
) -> dict.Dict(replica_id.ReplicaId, Int)
Extract the internal clock dictionary from a VersionVector.
Returns a Dict(ReplicaId, Int) mapping replica IDs to their clock values.
Useful for serialization or when you need direct access to the raw clock
data. Prefer the higher-level API (get, compare, merge) for most
use cases.
pub fn to_json(vv: VersionVector) -> json.Json
Encode a VersionVector as a self-describing JSON value.
Produces an envelope with type, v (schema version), and state.
Format: {"type": "version_vector", "v": 1, "state": {"clocks": {...}}}
Use from_json to decode the result back into a VersionVector.