Crdt.Patch

crdt · API reference

Patch container and batch operations

Patch container and batch operations.

A Patch contains a sequence of operations that should be applied atomically to a CRDT document. The patch has a starting ID, and each operation within the patch is assigned consecutive IDs based on the span of previous operations.

The JSON format from conformance traces:

  {"id": [sid, time], "ops": [...operations...

Types

type t = {
  id : Clock.timestamp; (* Starting timestamp for this patch *)
  ops : Op.op_data list; (* Operations in the patch *)
}

A patch containing a sequence of operations. The id is the starting timestamp for this patch. Each operation's ID is computed from the starting ID plus the cumulative span of previous operations.

type batch = t list

A batch of patches to be applied together

Creation

val empty : Clock.timestamp -> t

Create an empty patch with the given starting ID

val create : id:Clock.timestamp -> ops:Op.op_data list -> t

Create a patch with the given ID and operations

val singleton : id:Clock.timestamp -> Op.op_data -> t

Create a patch from a single operation

Properties

val span : t -> int

Get the total ID span consumed by this patch. This is the sum of spans of all operations.

val length : t -> int

Get the number of operations in the patch

val is_empty : t -> bool

Check if the patch is empty

val end_id : t -> Clock.timestamp

Get the ending timestamp (exclusive) of this patch. This is the ID that the next patch would start at.

val op_id_at : t -> int -> Clock.timestamp option

Get the ID of a specific operation within the patch. Returns None if index is out of bounds.

Building

val add : t -> Op.op_data -> t

Add an operation to the end of the patch

val add_all : t -> Op.op_data list -> t

Add multiple operations to the end of the patch

val prepend : Op.op_data -> t -> t

Prepend an operation to the beginning of the patch. Note: This does NOT adjust the patch ID.

Iteration

val iter_with_id : (Clock.timestamp -> Op.op_data -> 'a) -> t -> unit

Iterate over operations with their IDs

val fold_with_id : ('a -> Clock.timestamp -> Op.op_data -> 'a) -> 'a -> t -> 'a

Fold over operations with their IDs

val map : (Op.op_data -> Op.op_data) -> t -> t

Map over operations

val filter : (Op.op_data -> bool) -> t -> t

Filter operations

Slicing

val slice : start:int -> stop:int -> t -> t

Get operations by index from start inclusive to stop exclusive.

val split_at : int -> t -> t * t

Split patch at index, returning (before, after)

Transformation

val rebase : new_id:Clock.timestamp -> t -> t

Rebase a patch to start at a new ID. This creates a new patch with the same operations but a different starting ID.

val concat : t -> t -> t

Concatenate two patches. The second patch's operations are appended. The resulting patch uses the first patch's ID.

Batch Operations

val empty_batch : batch

Create an empty batch

val batch_of_list : batch -> batch

Create a batch from a list of patches

val add_to_batch : t list -> t -> batch

Add a patch to a batch

val batch_span : t list -> int

Get total span of all patches in a batch

val batch_length : t list -> int

Get total number of operations in a batch

val batch_iter_with_id : 
  (Clock.timestamp -> Op.op_data -> 'a) ->
  t list ->
  unit

Iterate over all operations in a batch with their IDs

Pretty Printing

val pp : Format.formatter -> t -> unit

Pretty print a patch

val to_string : t -> string

Convert patch to string for debugging