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 direction
  • Equal: 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.

Search Document