https://github.com/reiddraper/knockbox
https://github.com/reiddraper/knockbox
Last synced: over 1 year ago
JSON representation
- Host: GitHub
- URL: https://github.com/reiddraper/knockbox
- Owner: reiddraper
- License: apache-2.0
- Created: 2011-11-10T19:56:07.000Z (over 14 years ago)
- Default Branch: master
- Last Pushed: 2012-03-11T22:54:59.000Z (over 14 years ago)
- Last Synced: 2025-03-11T11:51:42.901Z (over 1 year ago)
- Language: Clojure
- Homepage:
- Size: 187 KB
- Stars: 141
- Watchers: 6
- Forks: 4
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Knockbox
## Build status
[](http://travis-ci.org/reiddraper/knockbox)
knockbox is an eventual-consistency toolbox for Clojure,
and eventually the JVM in general. It's inspired by
[statebox](https://github.com/mochi/statebox) and
the paper
[A comprehensive study of Convergent and Commutative Replicated Data Types](http://hal.archives-ouvertes.fr/inria-00555588/).
Databases like [Riak](https://github.com/basho/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](http://reiddraper.com/introducing-knockbox/).
## Status
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:
```clojure
(resolve [a b]))
```
When it comes time to resolve sibling, you can resolve
a vector of them like this:
```clojure
;; 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.
## Sets
```clojure
(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
Registers are simple containers for values.
Currently there is one Register implementation with
last-write-wins semantics.
```clojure
(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
Maps are currently a work in progress, and don't
yet implement all of the necessary Java intefaces.
## Counters
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.
## Serialization
knockbox currently supports JSON serialization for the three
set types. Usage below:
```clojure
(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
Tests can be run by typing:
lein deps # this only needs to be done once
lein midje
## Documentation
Source documentation can be generated by typing:
lein deps
lein marg
`lein deps` only needs to be run once.