OpLogCrdt

interface OpLogCrdt<Id : Any, V, Op : Any>

An op-log CRDT, viewed as the stream of operations it holds rather than as a value.

A replica of Rga or Fugue is a log of small, immutable edits — "insert this here", "remove that", "I have forgotten these". Most consumers never see the log; they read the list it adds up to. This contract is for the one consumer that wants the edits themselves: something that writes each edit down as it happens, and keeps it after the replica that made it has moved on.

That is the whole reason this is a separate contract from Quilted. Merging two replicas (piece) makes forgetting contagious: a replica that has compacted an element propagates that compaction to everyone it merges with, so a long-memory peer cannot hold history a short-memory peer has dropped. Operations do not have that property — they are just facts about what happened — so a consumer fed operations can retain a year of them beside a replica retaining an hour.

The classification is the point

classify splits the log three ways (LogOp). LogOp.Insert and LogOp.Remove are content; LogOp.Compact is a record of forgetting. A write-only archive keeps the first two and discards the third, which is exactly what lets its history outlive its source's. Getting that split wrong is a data-loss bug, so it lives here, in the CRDT that mints the ops, and not in each consumer.

What this contract deliberately does not expose

operations is a Sequence — a view, which any future backing (a materialised cache, a paged store, a lazily-decoded segment) can stream. It is not the op-log field, and the concrete collection type behind it is not part of this contract. That representation independence is why this interface exists at all instead of the op-log simply being made public: publishing the field would pin its type as a compatibility commitment.

Instance-scoped, for now

classify and dotOf are instance methods, so a consumer cannot classify an op without a live CRDT in hand. That is acceptable for the append side — the path that classifies always holds the replica it is classifying for — but a replay-side validator, reading ops back from storage with no replica available, would want them free-standing. Splitting them out is a source-compatible change if that day comes.

Type Parameters

Id

the element-identity type (RgaId / FugueId).

V

the element type carried by inserts.

Op

the operation type (RgaOp<V> / FugueOp<V>).

Inheritors

Functions

Link copied to clipboard
abstract fun classify(op: Op): LogOp<Id>

Classify op as an LogOp — insert, remove, or compaction record.

Link copied to clipboard
abstract fun dotOf(id: Id): Dot

The causal Dot (replica, seq) that id belongs to.

Link copied to clipboard
abstract fun operations(): Sequence<Op>

Every operation this replica currently holds, in no guaranteed order.

Link copied to clipboard
abstract fun opSerializer(vSerializer: KSerializer<V>): KSerializer<Op>

The canonical KSerializer for this CRDT's operations, threading vSerializer through the element type.