Options
All
  • Public
  • Public/Protected
  • All
Menu

Class CTotalOrder

A collaborative abstract total order on Positions.

This is a low-level API intended for internal use by list CRDT implementations. In most apps, you are better off using CValueList or CList.

A CTotalOrder represents the core of a list CRDT: a collaborative list of Positions that can be expanded over time, but without any associated values. Instead, you use a LocalList to map a subset of Positions to values, in list order with indexed access. Note that LocalList is a local (non-collaborative) data structure, i.e., its value assignments are not automatically replicated.

Waypoints

Internally, CTotalOrder stores an append-only log of Waypoints. The allowed Positions correspond to pairs (waypoint, valueIndex) where waypoint is an existing Waypoint and valueIndex is a nonnegative number. Methods decode, encode, and encodeAll convert between the two representations.

Note that waypoints and positions are only created, never destroyed. To create new positions (creating a new waypoint if needed), call createPositions.

List Order

The positions are ordered using a tree. Each waypoint's positions form a descending, left-to-right branch in the tree rooted at the position with valueIndex 0. The position with valueIndex 0 is a child of the waypoint's parent position, on the side given by Waypoint.isRight.

The position order is then an in-order traversal of this tree: we traverse a position's left children, then visit the position, then traverse its right children. Same-side siblings are ordered by the tiebreakers:

  • A position belonging to the same waypoint as the parent (just with valueIndex + 1) is to the left of any other siblings.
  • Other siblings (each belonging to different waypoints and with valueIndex 0) are sorted lexicographically by their waypoints' Waypoint.senderIDs. We call these waypoint children.

Note that positions belonging to the same waypoint are contiguous when first created. Later, (left-side) waypoint children may appear between them.

Hierarchy

Index

Constructors

Properties

name: string

Internal (this/parent) use only.

This Collab's name, which distinguishes it among its siblings in the tree of Collabs.

parent: Parent

Internal (this/parent) use only.

This Collab's parent in the tree of Collabs.

rootWaypoint: Waypoint

The root waypoint.

The special position (rootWaypoint, 0) is the root of the tree of positions. It technically appears first in the total order but is usually not used.

runtime: IRuntime

The ambient IRuntime.

Use this to access utilities like IRuntime.replicaID.

Methods

  • canGC(): boolean
  • Internal (parent) use only.

    If this Collab is in its initial, post-constructor state, then this method may (but is not required to) return true; otherwise, it returns false.

    By default, this method always returns false; override to change.

    If this method returns true:

    1. The parent may choose to weakly reference this object to save memory (e.g., CLazyMap does so). If this becomes garbage collected, then is needed later, the parent will recreate it using the same constructor call.
    2. The parent may skip calling save during saving. When loading the resulting saved state, the parent will call load(null, meta). load should process this as if called with the output of save from a garbage-collectable state. For a nontrivial example, see [[CMultiValueMap.load]]'s implementation.

    Returns boolean

  • createPositions(prevPosition: null | string, nextPosition: null | string, count: number): string[]
  • Creates count new positions between prevPosition and nextPosition. The positions are created collaboratively (replicated on all devices).

    If !(prevPosition < nextPosition), behavior is undefined.

    Note that this might not actually send a message.

    throws

    If count <= 0.

    Parameters

    • prevPosition: null | string

      The previous position, or null to create positions at the beginning of the list.

    • nextPosition: null | string

      The next position, or null to create positions at the end of the list.

    • count: number

      The number of positions to create.

    Returns string[]

    The created Positions, in list order. Internally, they use the same waypoint with contiguously increasing valueIndex.

  • decode(position: string): [waypoint: Waypoint, valueIndex: number]
  • Returns the pair (waypoint, valueIndex) encoded by position, throwing an error if the position is invalid.

    Invert with encode.

    Parameters

    • position: string

    Returns [waypoint: Waypoint, valueIndex: number]

  • Emits an event, which triggers all the registered event handlers.

    See CollabEventsRecord for advice on what events to emit.

    This is a wrapper around EventEmitter.emit that forces events to extend CollabEvent and also emits an "Any" event.

    Type Parameters

    • K extends "Any"

    Parameters

    • eventName: K
    • event: CollabEventsRecord[K] & CollabEvent
    • Optional options: { skipAnyEvent?: boolean }
      • Optional skipAnyEvent?: boolean

        Set to true to skip emitting an "Any" event.

    Returns void

  • encode(waypoint: Waypoint, valueIndex: number): string
  • Returns the Position representation of (waypoint, valueIndex).

    Invert with decode.

    Parameters

    Returns string

  • encodeAll(waypoint: Waypoint, valueIndex: number, count: number): string[]
  • Returns the positions representing (waypoint, valueIndex + i) for i in range [0, count).

    Parameters

    • waypoint: Waypoint
    • valueIndex: number
    • count: number

    Returns string[]

  • finalize(): void
  • Internal (parent) use only.

    Called by this Collab's parent when it has been deleted from a collection on the local replica and can no longer be used (e.g., due to CSet.delete on this or an ancestor). A Collab implementation can implement this method to clean up external resources, e.g., associated DOM elements.

    finalize has no relation to the JavaScript garbage collector or canGC.

    By default, this method does nothing.

    Returns void

  • getWaypoint(senderID: string, counter: number): Waypoint
  • Returns the waypoint with the given senderID and counter, throwing an error if it does not exist.

    Parameters

    • senderID: string
    • counter: number

    Returns Waypoint

  • Internal (parent) use only.

    Called by this Collab's parent to load saved state. You may assume that the saved state was generated by save on some replica of this Collab, possibly in a different collaboration session, with guarantees set by the runtime.

    This method may also be called with savedStateTree = null; you should ignore such calls (i.e., return immediately) unless you override canGC. If you do override canGC, see that method's docs for instructions.

    Parameters

    Returns void

  • loadPrimitive(savedState: null | Uint8Array, _meta: SavedStateMeta): void
  • Called by this Collab's parent to load some saved state. You may assume that the saved state was generated by savePrimitive on some replica of this Collab, possibly in a different collaboration session, with guarantees set by the runtime.

    This method may also be called with savedState = null; you should ignore such calls (i.e., return immediately) unless you override canGC. If you do override canGC, see that method's docs for instructions.

    Parameters

    Returns void

  • Registers an event handler that is triggered when the event happens.

    Type Parameters

    • K extends "Any"

    Parameters

    • eventName: K

      Name of the event to listen on.

    • handler: ((event: CollabEventsRecord[K], caller: CTotalOrder) => void)

      Callback that handles the event.

    • Optional options: { once?: boolean }
      • Optional once?: boolean

        If true, the event handler is triggered at most once (the next time the event happens), then unsubscribed.

    Returns (() => void)

    An "off" function that removes the event handler when called.

      • (): void
      • Registers an event handler that is triggered when the event happens.

        Returns void

        An "off" function that removes the event handler when called.

  • receive(messageStack: (string | Uint8Array)[], meta: MessageMeta): void
  • Internal (parent) use only.

    Receives a message sent by send on a local or remote replica of this Collab.

    This method processes the message, changes the local state accordingly, and emits events describing the local changes.

    This method should make assumptions and ensure consistency guarantees appropriate to its use case. For example, CRDTs may assume eventual, exactly-once, causal-order message delivery, and they must ensure strong eventual consistency.

    Parameters

    Returns void

  • receivePrimitive(message: string | Uint8Array, meta: MessageMeta): void
  • Receives a message sent by sendPrimitive on a local or remote replica of this CPrimitive.

    This method processes the message, changes the local state accordingly, and emits events describing the local changes.

    This method should make assumptions and ensure consistency guarantees appropriate to its use case. For example, CRDTs may assume eventual, exactly-once, causal-order message delivery, and they must ensure strong eventual consistency.

    See Collab.receive.

    Parameters

    Returns void

  • Internal (parent) use only.

    Returns saved state describing the current state of this Collab.

    The saved state may later be passed to load on a replica of this Collab, possibly in a different collaboration session, with rules set by the runtime. For example, CRuntime allows load at any time; it must then act as a merge operation (like a state-based CRDT), applying all updates that the saved replica had applied before saving, ignoring duplicates.

    save may be called at any time, possibly many times while an app is running. Calling save should not affect this Collab's user-visible state.

    For convenience, the saved state may be expressed as a tree of Uint8Arrays instead of just a single Uint8Array; see [[SaveStateTree]]'s docs.

    Returns SavedStateTree

    The saved state.

  • savePrimitive(): Uint8Array
  • Returns saved state describing the current state of this Collab.

    The saved state may later be passed to loadPrimitive on a replica of this Collab, possibly in a different collaboration session, with rules set by the runtime. For example, CRuntime allows load to be called only at the beginning of a session, before sending or receiving any messages.

    savePrimitive may be called at any time, possibly many times while an app is running. Calling savePrimitive should not affect this Collab's user-visible state.

    Returns Uint8Array

    The saved state.

  • send(messageStack: (string | Uint8Array)[], metaRequests: MetaRequest[]): void
  • Broadcasts a message to other replicas of this Collab. The message will be delivered to all replicas' receive, including locally.

    For convenience, the message may be expressed as a stack of (Uint8Array | string), instead of just a single Uint8Array. This is useful for parents sending messages on behalf of their children; see the implementation of CObject for an example.

    Parameters

    • messageStack: (string | Uint8Array)[]

      The message to send, in the form of a stack of Uint8Arrays. Note that this method may mutate it in-place.

    • metaRequests: MetaRequest[]

      A stack of metadata requests. The runtime will use the union of these when creating the MessageMeta for receive. Note that the stack need not align with messageStack, and this method may mutate it in place.

    Returns void

  • sendPrimitive(message: string | Uint8Array, metaRequest?: MetaRequest): void
  • Broadcasts a message to other replicas of this Collab. The message will be delivered to all replicas' receivePrimitive, including locally.

    Call this method instead of Collab.send.

    Parameters

    Returns void

Generated using TypeDoc