 (defn kvs-entry-by-key [kvs key]
   (kvs-entry-by-key-sq kvs key (kvs-sq-by-key kvs key)))
 
-; TODO: Track age, utilization, compaction for simulated performance.
-
-; TODO: Cannot use atoms because they prevent time travel.
-
-; TODO: Add snapshot ability.
-
-(defn kvs-check [m work-fn]
+(defn kvs-check [kvs-ident work-fn]
   (fn [state] ; Meant to be used as work-fn for state-work function.
-    (if-let [[name uuid] (:kvs-ident m)]
+    (if-let [[name uuid] kvs-ident]
       (if-let [kvs (get-in state [:kvss name])]
         (if (= uuid (:uuid kvs))
           (work-fn state kvs)

(ns cbfg.kvs
  (:require-macros [cbfg.act :refer [act act-loop achan
                                     aput-close aput atake aalts]])
  (:require [cbfg.misc :refer [dissoc-in]]))

; A kvs is an abstraction of ordered-KV store.  Concrete examples

        [state {:status :not-found :sub-status :no-kvs}])
      [state {:status :invalid :sub-status :no-kvs-ident}])))

(defn state-work [actx state-ch m work-fn & opt-done-ch]
  (act state-work actx
       (let [done-ch (or opt-done-ch (achan state-work))]
         (aput state-work state-ch [work-fn done-ch])
         (aput state-work (:res-ch m)
               (merge m (or (atake state-work done-ch) {:status :error}))))))

(def op-handlers
  {:kvs-open
   (fn [actx state-ch m]
     (state-work actx state-ch m
                 (kvs-check (:kvs-ident m)
                            #(if-let [name (:name m)]
                               (if-let [kvs (get-in % [:kvss name])]
                                 [% {:status :ok :kvs-ident [name (:uuid kvs)]}]
                                 [(-> %
                                      (update-in [:kvss name]
                                                 (make-kvs name (:next-uuid %)))
                                      (assoc :next-uuid (inc (:next-uuid %))))
                                  {:status :ok :kvs-ident [name (:next-uuid %)]}])
                               [% {:status :invalid :sub-status :no-name}]))))

   :kvs-remove
   (fn [actx state-ch m]
     (state-work actx state-ch m
                 (kvs-check (:kvs-ident m)
                            (fn [state kvs]
                              [(dissoc-in state [:kvss (:name kvs)])
                               {:status :ok}]))))

   :multi-get
   (fn [actx state-ch m]
     (let [keys (:keys m)
           res-m (dissoc m :keys)
           res-ch (:res-ch m)
           done-ch (achan actx)
           work-fn (fn [state kvs]
                     [state
                      (act multi-get actx
                           (doseq [key (:keys m)]
                             (if-let [entry (kvs-entry-by-key kvs key)]
                               (aput multi-get res-ch
                                     (merge res-m
                                            {:partial :ok :key key :entry entry}))
                               (aput multi-get res-ch
                                     (merge res-m
                                            {:partial :not-found :key key}))))
                           (aput multi-get done-ch {:status :ok}))])]
       (state-work actx state-ch m
                   (kvs-check (:kvs-ident m) work-fn) done-ch)))

   :multi-change
   (fn [actx state-ch [res-ch name changes]])
