No description or website provided.
Failed to load latest commit information.
src/knockbox Add noop GC to set implementations. Add tests Mar 11, 2012
test/knockbox/test Add noop GC to set implementations. Add tests Mar 11, 2012
.gitignore Add copyright notice and update gitignore Nov 12, 2011
.travis.yml Fix ns spelling error, use midje for tests Jan 1, 2012
LICENSE add license Nov 11, 2011
NOTICE Add note about state of Maps and Counters Mar 11, 2012
project.clj Add cheshire to dependencies Jan 8, 2012


Build status

Build Status

knockbox is an eventual-consistency toolbox for Clojure, and eventually the JVM in general. It's inspired by statebox and the paper A comprehensive study of Convergent and Commutative Replicated Data Types.

Databases like Riak let you trade consistency for availability. This means that you can have two conflicting values for a particular key. Resolving these conflicts is up to application-logic in the database clients. Certain data-types and operations are suited for automatic conflict-resolution. This project is a collection of these data-types and operations.

There is also a blog post about knockbox here.


knockbox is currently in development and the API will be changing quickly, without notice.

Resolution Protocol

Each of the data type in knockbox implement the knockbox.resolvable/Resolvable protocol, which is currently simply:

(resolve [a b]))

When it comes time to resolve sibling, you can resolve a vector of them like this:

;; notice the namespace difference
(knockbox.core/resolve [a b c d e])

The data types also implement any appropriate Java Interfaces and Clojure Protocols. The different knockbox set implementations, for example, can be used just like Clojure Sets.


(require 'knockbox.sets)

;; last-write-wins set
(def a (knockbox.sets/lww))
;; => #{}

;; two-phase set
(def b (knockbox.sets/two-phase))
;; => #{}

;; observed-remove set 
(def c (knockbox.sets/observed-remove))
;; => #{}

(disj a :foo)
;; => #{}

(conj b :bar)
;; => #{:bar}


Registers are simple containers for values. Currently there is one Register implementation with last-write-wins semantics.

(require '(knockbox core registers))

;; the only argument to lww is the value
;; of the register
(def a (knockbox.registers/lww "1"))
(def b (knockbox.registers/lww "2"))
(def c (knockbox.registers/lww "3"))

;; the value can be queried like
(.value a)
;; => "1"

(.value (knockbox.core/resolve [c b a]))
;; => "3"


Maps are currently a work in progress, and don't yet implement all of the necessary Java intefaces.


Counters with an unbounded number of actors (ie. each of your JVM's + Pids) are a tough garbage collection problem. I haven't yet figured out a way to deal with this. Finding a way to bound the number of actors, and not doing GC may be another option.


knockbox currently supports JSON serialization for the three set types. Usage below:

(require '(knockbox sets core))

(def a (knockbox.sets/lww))

(def b (conj a :foo :bar :baz))

(def j (knockbox.core/to-json b))

(def c (knockbox.core/from-json j))

(= b c)
;; => true


Tests can be run by typing:

lein deps # this only needs to be done once
lein midje


Source documentation can be generated by typing:

lein deps
lein marg

lein deps only needs to be run once.