Update tests, client also sends ACK messages
This commit is contained in:
parent
87b88f9340
commit
16b61063ec
3 changed files with 42 additions and 26 deletions
|
@ -10,18 +10,17 @@
|
||||||
(defmulti handle-event (fn [event] (:type event)))
|
(defmulti handle-event (fn [event] (:type event)))
|
||||||
|
|
||||||
(defmethod handle-event :diff [{:keys [hash diff states shadow client?] :as msg}]
|
(defmethod handle-event :diff [{:keys [hash diff states shadow client?] :as msg}]
|
||||||
(let [shadow (sync/get-history-state states hash)]
|
(let [history-shadow (sync/get-history-state states hash)]
|
||||||
(if shadow
|
(if history-shadow
|
||||||
(let [new-states (sync/apply-diff states diff)
|
(let [new-states (sync/apply-diff states diff)
|
||||||
new-shadow (diff/patch-state shadow diff)
|
new-shadow (diff/patch-state history-shadow diff)
|
||||||
{new-diff :diff new-hash :hash} (sync/diff-states (sync/get-current-state new-states) new-shadow)]
|
{new-diff :diff new-hash :hash} (sync/diff-states (sync/get-current-state new-states) new-shadow)]
|
||||||
(if client?
|
{:out-event (when-not (sync/empty-diff? diff)
|
||||||
{:new-states (sync/new-state (sync/get-current-state new-states))
|
(message/diff-msg new-diff new-hash))
|
||||||
:new-shadow new-shadow}
|
:new-states (if client?
|
||||||
{:out-event (when-not (sync/empty-diff? diff)
|
(sync/new-state (sync/get-current-state new-states))
|
||||||
(message/diff-msg new-diff new-hash))
|
new-states)
|
||||||
:new-states new-states
|
:new-shadow new-shadow})
|
||||||
:new-shadow (sync/get-current-state new-states)}))
|
|
||||||
(if client?
|
(if client?
|
||||||
{:out-event message/full-sync-request
|
{:out-event message/full-sync-request
|
||||||
:new-shadow shadow}
|
:new-shadow shadow}
|
||||||
|
@ -38,9 +37,9 @@
|
||||||
{:new-states (sync/new-state state)
|
{:new-states (sync/new-state state)
|
||||||
:new-shadow state})
|
:new-shadow state})
|
||||||
|
|
||||||
(defmethod handle-event :new-state [{:keys [state states shadow]}]
|
(defmethod handle-event :new-state [{:keys [client? state states shadow] :as event}]
|
||||||
(let [{:keys [diff hash]} (sync/diff-states state shadow)]
|
(let [{:keys [diff hash]} (sync/diff-states state shadow)]
|
||||||
{:new-shadow shadow
|
{:new-states (sync/add-history-state states state)
|
||||||
:out-event (when-not (sync/empty-diff? diff) (message/diff-msg diff hash))}))
|
:out-event (when-not (sync/empty-diff? diff) (message/diff-msg diff hash))}))
|
||||||
|
|
||||||
(defn make-agent
|
(defn make-agent
|
||||||
|
@ -53,15 +52,15 @@
|
||||||
{:keys [new-states new-shadow out-event]} (handle-event event)]
|
{:keys [new-states new-shadow out-event]} (handle-event event)]
|
||||||
(when (and new-states (not= states new-states)) (reset! states* new-states))
|
(when (and new-states (not= states new-states)) (reset! states* new-states))
|
||||||
(when out-event (a/put! >remote out-event))
|
(when out-event (a/put! >remote out-event))
|
||||||
(recur shadow)))))))
|
(recur (if new-shadow new-shadow shadow))))))))
|
||||||
|
|
||||||
(defn make-server-agent
|
(defn make-server-agent
|
||||||
([in out states] (make-agent false in out states))
|
([<remote >remote states] (make-agent false <remote >remote states))
|
||||||
([in out states initial-shadow] (make-agent false in out states initial-shadow)))
|
([<remote >remote states initial-shadow] (make-agent false <remote >remote states initial-shadow)))
|
||||||
|
|
||||||
(defn make-client-agent
|
(defn make-client-agent
|
||||||
([in out states] (make-agent true in out states))
|
([<remote >remote states] (make-agent true <remote >remote states))
|
||||||
([in out states initial-shadow] (make-agent true in out states initial-shadow)))
|
([<remote >remote states initial-shadow] (make-agent true <remote >remote states initial-shadow)))
|
||||||
|
|
||||||
(def states (atom []))
|
(def states (atom []))
|
||||||
(def empty-state sync/empty-state)
|
(def empty-state sync/empty-state)
|
||||||
|
|
|
@ -32,11 +32,9 @@
|
||||||
(into [] (rest new-states))
|
(into [] (rest new-states))
|
||||||
new-states)))))
|
new-states)))))
|
||||||
|
|
||||||
(defn diff-states [states shadow]
|
(defn diff-states [state shadow]
|
||||||
(let [state states;(get-current-state states)
|
{:hash (hasch/uuid shadow)
|
||||||
]
|
:diff (diff/diff-states shadow state)})
|
||||||
{:hash (hasch/uuid shadow)
|
|
||||||
:diff (diff/diff-states shadow state)}))
|
|
||||||
|
|
||||||
(defn apply-diff [states diff]
|
(defn apply-diff [states diff]
|
||||||
(let [new-state (diff/patch-state (get-current-state states) diff)]
|
(let [new-state (diff/patch-state (get-current-state states) diff)]
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
:state s}))
|
:state s}))
|
||||||
(into [])))
|
(into [])))
|
||||||
|
|
||||||
(fact "Applies diff and returns empty diff when no server changes"
|
(fact "Server applies diff and returns empty diff when no server changes"
|
||||||
(let [states (hashed-states
|
(let [states (hashed-states
|
||||||
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}})
|
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}})
|
||||||
event {:type :diff
|
event {:type :diff
|
||||||
|
@ -23,12 +23,31 @@
|
||||||
new-states => (hashed-states
|
new-states => (hashed-states
|
||||||
{:grubs {"1" {:completed false, :text "2 apples"}}, :recipes {}}
|
{:grubs {"1" {:completed false, :text "2 apples"}}, :recipes {}}
|
||||||
{:grubs {"1" {:completed true, :text "2 apples"}}, :recipes {}})
|
{:grubs {"1" {:completed true, :text "2 apples"}}, :recipes {}})
|
||||||
|
new-shadow {:grubs {"1" {:completed true, :text "2 apples"}}, :recipes {}}
|
||||||
out-event => {:type :diff
|
out-event => {:type :diff
|
||||||
:diff {:grubs {:deleted #{}, :updated nil}
|
:diff {:grubs {:deleted #{}, :updated nil}
|
||||||
:recipes {:deleted #{}, :updated nil}}
|
:recipes {:deleted #{}, :updated nil}}
|
||||||
:hash (:hash (last new-states))}))
|
:hash (:hash (last new-states))}))
|
||||||
|
|
||||||
(fact "Applies diff and returns changes when server has changed"
|
(fact "Client applies diff, clears history, updates shadow, returns empty diff when no client changes"
|
||||||
|
(let [states (hashed-states
|
||||||
|
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}})
|
||||||
|
event {:type :diff
|
||||||
|
:diff {:grubs {:updated {"1" {:completed true}} :deleted #{}}}
|
||||||
|
:hash (:hash (first states))
|
||||||
|
:states states
|
||||||
|
:shadow (:state (last states))
|
||||||
|
:client? true}
|
||||||
|
{:keys [new-states new-shadow out-event]} (state/handle-event event)]
|
||||||
|
new-states => (hashed-states
|
||||||
|
{:grubs {"1" {:completed true, :text "2 apples"}}, :recipes {}})
|
||||||
|
new-shadow => {:grubs {"1" {:completed true, :text "2 apples"}}, :recipes {}}
|
||||||
|
out-event => {:type :diff
|
||||||
|
:diff {:grubs {:deleted #{}, :updated nil}
|
||||||
|
:recipes {:deleted #{}, :updated nil}}
|
||||||
|
:hash (:hash (last new-states))}))
|
||||||
|
|
||||||
|
(fact "Server applies diff and returns changes when server has changed"
|
||||||
(let [states (hashed-states
|
(let [states (hashed-states
|
||||||
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
||||||
{:grubs {"1" {:text "2 apples" :completed false}
|
{:grubs {"1" {:text "2 apples" :completed false}
|
||||||
|
@ -56,7 +75,7 @@
|
||||||
:hash (hasch/uuid {:grubs {"1" {:text "2 apples" :completed true}}
|
:hash (hasch/uuid {:grubs {"1" {:text "2 apples" :completed true}}
|
||||||
:recipes {}})}))
|
:recipes {}})}))
|
||||||
|
|
||||||
(fact "Force full sync if client is out of sync"
|
(fact "Server forces full sync if client is out of sync"
|
||||||
(let [states (hashed-states
|
(let [states (hashed-states
|
||||||
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
||||||
{:grubs {"1" {:text "2 apples" :completed false}
|
{:grubs {"1" {:text "2 apples" :completed false}
|
||||||
|
@ -76,7 +95,7 @@
|
||||||
"2" {:text "3 onions" :completed false}}
|
"2" {:text "3 onions" :completed false}}
|
||||||
:recipes {}}}))
|
:recipes {}}}))
|
||||||
|
|
||||||
(fact "Full sync if client requests it"
|
(fact "Server sends full sync if client requests it"
|
||||||
(let [states (hashed-states
|
(let [states (hashed-states
|
||||||
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
{:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
|
||||||
{:grubs {"1" {:text "2 apples" :completed false}
|
{:grubs {"1" {:text "2 apples" :completed false}
|
||||||
|
|
Loading…
Reference in a new issue