npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@concordant/c-crdtlib

v1.0.6

Published

The Concordant Conflict-Free Replicated Datatypes (CRDT) library

Downloads

18

Readme

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.