compacted method

RgaList<T> compacted()

Returns a copy with every tombstone purged.

Deleted elements normally stay as tombstones so concurrent inserts anchored to them keep their position; over the life of a document they accumulate without bound. Compaction rebuilds the sequence as a linear chain of only the visible elements — element ids are preserved, so cursor anchors (elementIdAt/indexOfId) stay valid, order is exactly the current visible order, and the Lamport counter continues from where it was (new local inserts cannot collide). The rewrite is a pure function of the synced state, so replicas compacting the same state produce identical results.

⚠️ Coordination contract: compact only at a synchronization barrier (all replicas have merged this state — e.g. when persisting a checkpoint or when a single writer holds the document). Merging a compacted list with a stale replica that never observed a deletion resurrects that element (its tombstone is gone), and elements whose anchors were rewritten reconcile through merge's deterministic same-id resolution — convergent on every replica, but the visible order around the stale edits may shift once.

Implementation

RgaList<T> compacted() {
  final nodes = <String, RgaNode<T>>{};
  String? origin;
  for (final node in _visible()) {
    nodes[node.id] = RgaNode<T>(
      replicaId: node.replicaId,
      counter: node.counter,
      origin: origin,
      value: node.value,
    );
    origin = node.id;
  }
  return RgaList._(replicaId, nodes, _counter);
}