~severeoverfl0w/rich-crdts

447758b3 — Dominic Monroe 1 year, 4 months ago
Fix empty in ClojureMap
e51d6ac4 — Dominic Monroe 1 year, 4 months ago
Fix JDK11 compatibility
0f94b3fd — Dominic Monroe 1 year, 4 months ago
Revert "Add indirection to readers"

refs

master
browse  log 

clone

read-only
https://git.sr.ht/~severeoverfl0w/rich-crdts
read/write
git@git.sr.ht:~severeoverfl0w/rich-crdts

You can also use your local clone with git send-email.

#Rich LWW CRDTs

(working name)

LWW CRDTs for collections (sets, registers/maps).

All are serialization friendly, and data readers are included. Note that when serializing, the comparator will not be included, so you will need to communicate that out of band. This is due to the comparator being non-serializable (it's an object!).

All are aggressive about history pruning, and offer no undo/time travel capabilities.

#Core

Provides functions for adding a new value (either a k for a set, or a [k v] for a map). disj allows for removing a k at time. Convenience function conj-at and disj-at allow specifying the time only once for batch operations.

(require '[io.dominic.rich-crdt.core :as rich-crdt])
;; Add two keys to a set, with distinct times
(rich-crdt/conj set-crdt [:a #inst "2020"] [:b #inst "1990"])
;; Add two key/vals to a register, with distinct times.  Result is {:a "value" :b "othervalue"}.
(rich-crdt/conj reg-crdt [[:a "value"] #inst "2020"] [[:b "othervalue"] #inst "1990"])
;; Remove two keys in the past, works on sets and registers
(rich-crdt/disj lww-crdt [:a #inst "2000"] [:b #inst "1990"])

;; Add :a :b to a set in 2020
(rich-crdt/conj-at set-crdt #inst "2020" :a :b)
;; Add kvs [:a "value"] [:b "othervalue"] to a set in 2020
(rich-crdt/conj-at reg-crdt #inst "2020" :a :b)
;; Remove :a :b in 2020
(rich-crdt/disj-at lww-crdt #inst "2090" :a :b)

;; Merge two crdts of the same type.
(rich-crdt/merge lww-crdt lww-crdt2)

#Last Write Wins Register

Like a map, but with a time dimension.

(require '[io.dominic.rich-crdt.lww-register :as lwwr])

(lwwr/lww-register) ;; empty lww register
(lwwr/->clj (lwwr/lww-register)) ;; => {}
(lwwr/lww-register [[:a 1] 10] [[:b 2] 20]) ;; => {:a 1 :b 2}
;; Supports custom time comparators, fairly useless example but I'm sure you
can come up with something useful.  Default is compare.
(lwwr/lww-register-by (Collator/getInstance) [[:a 1] "10"] [[:b 2] "20"]) ;; => {:a 1 :b 2}

#Last Write Wins Element Set

Like a set, but with a time dimension.

(require '[io.dominic.rich-crdt.lww-element-set :as lwwes])

(lwwes/lww-element-set) ;; empty lww element set
(lwwes/->clj (lwwr/lww-element-set)) ;; => #{}
(lwwes/lww-element-set [:a 10] [:b 20]) ;; => #{:a :b}
;; Custom comparator
(lwwes/lww-element-set-by (Collator/getInstance) [:a "10"] [:b "20"]) ;; => #{:a :b}