Refactor - wip
This commit is contained in:
parent
5a66361746
commit
fe5bd00427
2 changed files with 84 additions and 0 deletions
|
@ -5,6 +5,33 @@
|
|||
[clojure.core.async :as a :refer [<! >! chan go]]
|
||||
[hasch.core :as hasch]))
|
||||
|
||||
(def initial-state {:hash (hasch/uuid cs/empty-state)
|
||||
:state cs/empty-state})
|
||||
(def states (atom [initial-state]))
|
||||
|
||||
(defn get-history-state [states hash]
|
||||
(:state (first (filter #(= (:hash %) hash) states))))
|
||||
|
||||
(defn add-history-state [current new-state]
|
||||
(let [{:keys [state hash]} (first current)
|
||||
new-hash (hasch/uuid new-state)]
|
||||
(if (= hash new-hash)
|
||||
current
|
||||
(conj current {:hash hash :state state}))))
|
||||
|
||||
(defn receive-diff [states diff shadow-hash]
|
||||
(let [state (:state (first states))
|
||||
shadow (get-history-state states shadow-hash)]
|
||||
(if shadow
|
||||
{:new-state (diff/patch-state state diff)
|
||||
:new-shadow (diff/patch-state shadow diff)
|
||||
:full-sync? false}
|
||||
{:new-state state
|
||||
:new-shadow state
|
||||
:full-sync? true})))
|
||||
|
||||
|
||||
|
||||
(def state (atom cs/empty-state))
|
||||
(def to-db (atom nil))
|
||||
(def to-all (chan))
|
||||
|
@ -26,6 +53,7 @@
|
|||
{:grubs (util/map-by-key :id grubs)
|
||||
:recipes (util/map-by-key :id recipes)})
|
||||
|
||||
|
||||
(defn sync-new-client! [to from]
|
||||
(let [client-id (java.util.UUID/randomUUID)
|
||||
client-state (atom cs/empty-state)
|
||||
|
|
56
src/test/grub/test/unit/state.clj
Normal file
56
src/test/grub/test/unit/state.clj
Normal file
|
@ -0,0 +1,56 @@
|
|||
(ns grub.test.unit.state
|
||||
(:require [grub.state :as s]
|
||||
[grub.common-state :as cs]
|
||||
[clojure.test :refer :all]
|
||||
[hasch.core :as hasch]))
|
||||
|
||||
(deftest apply-diff-normally
|
||||
;; Apply changes and return ACK for in sync client/server
|
||||
(let [state {:grubs {"1" {:text "2 apples" :completed false}}
|
||||
:recipes {}}
|
||||
hash (hasch/uuid state)
|
||||
states [{:hash hash :state state}]
|
||||
diff {:grubs {:updated {"1" {:completed true}} :deleted #{}}}
|
||||
shadow-hash hash
|
||||
{:keys [new-state new-shadow full-sync?]} (s/receive-diff states diff shadow-hash)]
|
||||
(do
|
||||
(is (= {:grubs {"1" {:text "2 apples" :completed true}}
|
||||
:recipes {}}
|
||||
new-state))
|
||||
(is (= {:grubs {"1" {:text "2 apples" :completed true}}
|
||||
:recipes {}}
|
||||
new-shadow))
|
||||
(is (not full-sync?)))))
|
||||
|
||||
(deftest server-state-changed
|
||||
;; Send differences back if server state changed
|
||||
(let [state {:grubs {"1" {:text "3 apples" :completed false}} :recipes {}}
|
||||
prev {:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
||||
states [{:hash (hasch/uuid state) :state state}
|
||||
{:hash (hasch/uuid prev) :state prev}]
|
||||
diff {:grubs {:updated {"1" {:completed true}} :deleted #{}}}
|
||||
shadow-hash (hasch/uuid prev)
|
||||
{:keys [new-state new-shadow full-sync?]} (s/receive-diff states diff shadow-hash)]
|
||||
(do
|
||||
(is (= {:grubs {"1" {:text "3 apples" :completed true}}
|
||||
:recipes {}}
|
||||
new-state))
|
||||
(is (= {:grubs {"1" {:text "2 apples" :completed true}}
|
||||
:recipes {}}
|
||||
new-shadow))
|
||||
(is (not full-sync?)))))
|
||||
|
||||
(deftest full-sync-if-client-too-far-out-of-sync
|
||||
;; Shadow hash not in history means client has fallen too far
|
||||
;; out of sync. Send a full sync
|
||||
(let [state {:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
||||
prev {:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
||||
states [{:hash (hasch/uuid state) :state state}
|
||||
{:hash (hasch/uuid prev) :state prev}]
|
||||
shadow-hash (hasch/uuid {:grubs {} :recipes {}})
|
||||
diff {:grubs {:updated {"1" {:completed true}} :deleted #{}}}
|
||||
{:keys [new-state new-shadow full-sync?]} (s/receive-diff states diff shadow-hash)]
|
||||
(do
|
||||
(is (= state new-state))
|
||||
(is (= state new-shadow))
|
||||
(is full-sync?))))
|
Loading…
Reference in a new issue