 
 
 (comment
- (def kv (make-in-memory-kvstore))
+  ;; create empty kvstores
+  (def kv1 (make-in-memory-kvstore))
+  (def kv2 (make-in-memory-kvstore))
 
- (def kv1 (set (set kv "a" :test 1) "a" :test 2))
+  ;; both same
+  (= kv1 kv2)
 
- (set kv "a" :test3 4)
+  ;; make some changes
+  (def kv1'
+    (-> kv1
+        (set "a" :test 1)
+        (set "a" :test 2)))
 
- (kv-get kv "a" :test)
-  kv
+  ;; restore state based on tx-log
+  (def kv2' (restore kv2 (tx-log kv1')))
 
- (snapshot kv)
-
- (tx-log kv))
+  ;; still the same
+  (= kv1' kv2')
+)

    "Set the given key to the give value. Returns the new KV store")

  (get [kvstore sourceId key]
    "It returns the current value of the given key. nil if not found.")


  (snapshot [kvstore]
    "Return the current value of the kvstore")

  (tx-log [kvstore]
    "Return the current Transaction log"))



(defrecord InMemoryKVstore [data]

  KV
  (set [kvstore sourceId key value]
    (InMemoryKVstore.
     (-> (:data kvstore)
         (update-in [:version] inc)
         (assoc-in [:snapshot sourceId key] value)
         ((fn [{:keys [version] :as data}]
            (update-in data [:tx-log] conj [version [sourceId key] value]))))))

  (snapshot [kvstore]
    (-> kvstore :data :snapshot))

  (tx-log [kvstore]
    (-> kvstore :data :tx-log))

  (get [kvstore sourceId key]
    (get-in kvstore [:data :snapshot sourceId key]))
)


(defn make-in-memory-kvstore []

(ns moebius.kv
  (:refer-clojure :exclude [set get remove update]))

;;
;; TODO: multi set function
;; TODO: force keys to string?
;; TODO: Do ve need the version? (think repartitioning)
;; TOOD: tx-log + compaction: single key or all keys x sourceId?
;;

(defprotocol KV
  "A key value store protocol"
