All Projects → concordant → c-crdtlib

concordant / c-crdtlib

Licence: MIT License
The Concordant Conflict-Free Replicated Datatypes (CRDT) library.

Programming Languages

kotlin
9241 projects
shell
77523 projects

Projects that are alternatives of or similar to c-crdtlib

rdoc
Conflict-free replicated JSON implementation in native Go
Stars: ✭ 76 (+261.9%)
Mutual labels:  crdt, crdts
CRDT-Redis
CRDTs implemented in Redis
Stars: ✭ 35 (+66.67%)
Mutual labels:  crdt, crdt-implementations
ron
Haskell implementation of RON and RON-RDT
Stars: ✭ 65 (+209.52%)
Mutual labels:  crdt, replicated-data-types
credt
CRDT-like data structures for building distributed, offline-first applications
Stars: ✭ 32 (+52.38%)
Mutual labels:  crdt, crdts
sworm
A user-friendly distributed process registry and process supervisor
Stars: ✭ 20 (-4.76%)
Mutual labels:  crdt
m-ld-js
m-ld Javascript engine
Stars: ✭ 18 (-14.29%)
Mutual labels:  crdt
y-crdt
Rust port of Yjs
Stars: ✭ 854 (+3966.67%)
Mutual labels:  crdt
awesome-collaboration
Collaborative editing of technical resources, article translation
Stars: ✭ 47 (+123.81%)
Mutual labels:  crdts
graph-crdt
Commutative graphs made for real-time, offline-tolerant replication
Stars: ✭ 47 (+123.81%)
Mutual labels:  crdt
godless
Peer-to-peer lite database over IPFS
Stars: ✭ 72 (+242.86%)
Mutual labels:  crdt
codepair
Real-time markdown editor for interviews, meetings & more...
Stars: ✭ 50 (+138.1%)
Mutual labels:  crdt
caracara
GEUT LABS. An experimental Dat based collaborative editor.
Stars: ✭ 33 (+57.14%)
Mutual labels:  crdt
netty-queue
Simple queue: java, json-rest, netty
Stars: ✭ 21 (+0%)
Mutual labels:  crdt
yorkie-js-sdk
Yorkie JavaScript SDK
Stars: ✭ 57 (+171.43%)
Mutual labels:  crdt
SyncedStore
SyncedStore CRDT is an easy-to-use library for building live, collaborative applications that sync automatically.
Stars: ✭ 1,053 (+4914.29%)
Mutual labels:  crdt
dynamic-data-and-capabilities
[ARCHIVED] Dynamic Data and Capabilities in IPFS Working Group
Stars: ✭ 57 (+171.43%)
Mutual labels:  crdt
slate-operational-transform
Slate Operational Transform Demo (used in production at Narration Box)
Stars: ✭ 34 (+61.9%)
Mutual labels:  crdt
jylis
A distributed in-memory database for Conflict-free Replicated Data Types (CRDTs). 🌱 ↔️
Stars: ✭ 68 (+223.81%)
Mutual labels:  crdt
bloomfilter
Bloomfilter written in Golang, includes rotation and RPC
Stars: ✭ 61 (+190.48%)
Mutual labels:  crdt
crdt
Dart implementation of Conflict-free Replicated Data Types (CRDTs)
Stars: ✭ 55 (+161.9%)
Mutual labels:  crdt

Conflict-Free Replicated Datatypes (CRDT) library

License

CRDT library in Kotlin for the Concordant platform API. This project is based on Kotlin multiplatform feature.

The Kotlin code is compiled to both JVM Bytecode and Javascript; see respective Getting Started sections for Java and Gradle and JavaScript/TypeScript and NPM below.

See also the full documentation of the master branch on GitLab pages.

The main repository is in the Inria gitlab (this is where you can post tickets). There is an identical clone in GitHub (tickets here might be ignored).

Getting Started

This library is delivered as both a Maven package and an NPM package.

Kotlin and Gradle

In your project configuration build file build.gradle.kts:

  • Ensure mavenCentral() is listed in the repositories{}.
  • Add the c-crdtlib Maven package as a dependency:
dependencies {
    implementation("io.concordant:c-crdtlib:x.y.z")
}

Usage

// consider refining to avoid wildcard import
import crdtlib.*

fun main() {
    // an Environment is required to manage Timestamps
    // (aka Operation IDs)
    val env = SimpleEnvironment(ClientUId("myClientUid"))

    // create and use a PNCounter:
    val ctr = PNCounter(env)
    ctr.increment(5)
    ctr.decrement(2)
    println(ctr.get())    // 3

    // Now a MVRegister, with two replicas:
    val lMVReg = MVRegister(env)
    lMVReg.assign("A")

    // simulate a remote client with an environment:
    val renv = SimpleEnvironment(ClientUId("remoteClientUid"))
    val rMVReg = MVRegister(env)

    // Merge local state to remote (using full state merge)
    // SimpleEnvironment automatically updates clock on merge
    rMVReg.merge(lMVReg)

    println(rMVReg.get())    // [A]

    // Modify both replicas concurrently
    lMVReg.assign("L")
    println(lMVReg.get())    // [L]

    rMVReg.assign("R")
    println(rMVReg.get())    // [R]

    // …then merge, using deltas

    // local -> remote
    // Use remote environment state as origin for delta
    val rVV = renv.getState()
    rMVReg.merge(lMVReg.generateDelta(rVV))
    println(rMVReg.get())    // [L, R]

    // remote -> local
    val lVV = lenv.getState()
    rMVReg.merge(lMVReg.generateDelta(lVV))
    println(lMVReg.get())    // [L, R]
}

JavaScript/TypeScript and NPM

Installation

Install the package:

$ npm i @concordant/c-crdtlib

Usage

As JavaScript does not support overloading, some method names differ from Kotlin names.

// Import the package
import {crdtlib} from @concordant/c-crdtlib;

// an Environment is required to manage Timestamps
// (aka Operation IDs)
const env = new crdtlib.utils.SimpleEnvironment(
            new crdtlib.utils.ClientUId("myClientUid"))

// create and use a PNCounter:
const ctr = new crdtlib.crdt.PNCounter(env)
ctr.increment(5)
ctr.decrement(2)
console.log(ctr.get())    // 3

// Now a MVRegister, with two replicas:
const lMVReg = new crdtlib.crdt.MVRegister(env)
lMVReg.assign("A")

// simulate a remote client with an environment:
const renv = new crdtlib.crdt.SimpleEnvironment(
            new crdtlib.utils.ClientUId("remoteClientUid"))
const rMVReg = new crdtlib.crdt.MVRegister(env)

// Merge local state to remote (using full state merge)
// SimpleEnvironment automatically updates clock on merge
rMVReg.merge(lMVReg)
console.log(rMVReg.get())    // [A]

// Modify both replicas concurrently
lMVReg.assign("L")
console.log(lMVReg.get())    // [L]

rMVReg.assign("R")
console.log(rMVReg.get())    // [R]

// …then merge, using deltas

// local -> remote
// Use remote environment state as origin for delta
const rVV = renv.getState()
rMVReg.merge(lMVReg.generateDelta(rVV))
console.log(rMVReg.get())    // [L, R]

// remote -> local
const lVV = lenv.getState()
rMVReg.merge(lMVReg.generateDelta(lVV))
console.log(lMVReg.get())    // [L, R]

CRDT Object API

The Concordant CRDT library currently provides three main classes of CRDTs:

  • Counters: store an integer value which can be decremented and incremented.
  • Registers: store a string value which can be reassigned.
  • Collections: store multiple string values which can be reassigned.

All object types support the following methods:

  • toJson serialises the object into a JSON string representing its current state.
  • DeltaCRDT.fromJson takes a JSON string and converts it to an object state of its corresponding type (and fails if the JSON does not parse properly).

The following sections briefly describes each type specificities.

Note: interfaces described here are not stable yet and will change in the next version of the CRDTlib.

Counters

PNCounter is an integer counter, with increment and decrement operations.

BCounter is a PNCounter whose value cannot become negative.

Counters provides an increment(nb) and decrement(nb) methods to modify their value; their content can be retrieved using the get() method.

Registers

LWWRegister stores a string; supports assignment; concurrent assignments resolve to a single value.

MVRegister stores a string; supports assignment; concurrent assignments are all retained.

Ratchet is a register with values taken from a custom semi-lattice. Concurrent assignments retain their least upper bound. Only string values with default ordering are currently supported.

All registers support assignment using the assign(value) method; their content can be retrieved using the get() method.

Collections

RGA is an ordered sequence of strings.

  • insertAt(idx, elem) inserts an element to the RGA.
  • removeAt(idx) removes an element.
  • getAt(idx) returns the element at a particular index.
  • get() returns the whole RGA content as a list.
  • iterator() returns an iterator over the RGA.

Maps

Map types currently only support Int, Double, Boolean, and String values. Specific methods are provided for each type (ex.: getString(key)), denoted here by method<TYPE>(). Note that a map may contain values of different types under the same key.

LWWMap maps strings to LWW scalar values.

  • put(key, value) adds or updates an element to the map.
  • delete<TYPE>(key) removes an element from the map.
  • get<TYPE>(key) retrieves the values associated with key.
  • iterator<TYPE>() returns an iterator on the map key-value pairs.

MVMap maps strings to MV scalar values. It supports the same methods as LWWMap, but values returned by get<TYPE>(key) and iterator<TYPE>() are multi-values (sets).

Map maps strings to LWW, MV and PNcounter values. Specific methods are provided for each merging strategy (LWW, MV or Cnt) denoted here by method<MS>() (ex.: getCnt(key)).

  • put<MS>(key, value) adds or updates an element to the map.
  • delete<MS><TYPE>(key) removes an element from the map.
  • get<MS><TYPE>(key) retrieves the values associated with key.
  • iterator<MS><TYPE>() returns an iterator on the map key-value pairs.
  • increment(key, nb), decrement(key, nb) increments/decrements the corresponding PNCounter value.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].