Factor out some client/server common state ops
This commit is contained in:
parent
b7b094b253
commit
bd08ea5ec5
4 changed files with 83 additions and 84 deletions
|
@ -14,52 +14,35 @@
|
||||||
{:grubs (util/map-by-key :id grubs)
|
{:grubs (util/map-by-key :id grubs)
|
||||||
:recipes (util/map-by-key :id recipes)})
|
:recipes (util/map-by-key :id recipes)})
|
||||||
|
|
||||||
(defn sync-remote-changes [to-client state* server-shadow]
|
|
||||||
(let [server-shadow* @server-shadow]
|
|
||||||
(when (not= state* server-shadow*)
|
|
||||||
(let [diff (sync/diff-states server-shadow* state*)
|
|
||||||
msg {:type :diff
|
|
||||||
:diff diff
|
|
||||||
:hash (hasch/uuid state*)
|
|
||||||
:shadow-hash (hasch/uuid server-shadow*)}]
|
|
||||||
(println "Sync because:")
|
|
||||||
(println "Server = " state*)
|
|
||||||
(println "Client = " server-shadow*)
|
|
||||||
(println "Diff:" diff)
|
|
||||||
(println "Send" (hasch/uuid server-shadow*) "->" (hasch/uuid state*))
|
|
||||||
(a/put! to-client msg)
|
|
||||||
;; TODO: only reset server shadow if send succeeds
|
|
||||||
(reset! server-shadow state*)))))
|
|
||||||
|
|
||||||
(defn sync-new-client! [to from]
|
(defn sync-new-client! [to from]
|
||||||
(let [client-id (java.util.UUID/randomUUID)
|
(let [client-id (java.util.UUID/randomUUID)
|
||||||
server-shadow (atom cs/empty-state)]
|
server-shadow (atom cs/empty-state)]
|
||||||
(add-watch state client-id (fn [k ref old new]
|
(add-watch state client-id (fn [_ _ _ new-state]
|
||||||
(sync-remote-changes to new server-shadow)))
|
(when-let [msg (cs/diff-states new-state server-shadow)]
|
||||||
|
(a/put! to msg)
|
||||||
|
(reset! server-shadow new-state))))
|
||||||
(a/go-loop []
|
(a/go-loop []
|
||||||
(let [{:keys [type diff hash shadow-hash] :as msg} (<! from)]
|
(when-let [{:keys [type diff hash shadow-hash] :as msg} (<! from)]
|
||||||
(if (not (nil? msg))
|
(condp = type
|
||||||
(do
|
:diff (do
|
||||||
(condp = type
|
(println "Received client diff:" shadow-hash "->" hash)
|
||||||
:diff (do
|
(println "Before shadow:" (hasch/uuid @server-shadow) @server-shadow)
|
||||||
(println "Received client diff:" shadow-hash "->" hash)
|
(if (= (hasch/uuid @server-shadow) shadow-hash)
|
||||||
(println "Before shadow:" (hasch/uuid @server-shadow) @server-shadow)
|
(println "Before hash check: good")
|
||||||
(if (= (hasch/uuid @server-shadow) shadow-hash)
|
(println "Before hash check: FAIL"))
|
||||||
(println "Before hash check: good")
|
(let [new-shadow (swap! server-shadow #(sync/patch-state % diff))
|
||||||
(println "Before hash check: FAIL"))
|
new-state (swap! state #(sync/patch-state % diff))]
|
||||||
(let [new-shadow (swap! server-shadow #(sync/patch-state % diff))
|
;; TODO: check if hashes match
|
||||||
new-state (swap! state #(sync/patch-state % diff))]
|
(println "After shadow:" (hasch/uuid new-shadow) new-shadow)
|
||||||
;; TODO: check if hashes match
|
(if (= (hasch/uuid new-shadow) hash)
|
||||||
(println "After shadow:" (hasch/uuid new-shadow) new-shadow)
|
(println "After hash check: good")
|
||||||
(if (= (hasch/uuid new-shadow) hash)
|
(println "After hash check: FAIL"))
|
||||||
(println "After hash check: good")
|
(>! @to-db diff)))
|
||||||
(println "After hash check: FAIL"))
|
:complete (let [new-state (reset! server-shadow @state)]
|
||||||
(>! @to-db diff)))
|
(a/put! to (cs/complete-sync-response new-state)))
|
||||||
:complete (let [new-state (reset! server-shadow @state)]
|
(println "Invalid msg:" msg))
|
||||||
(a/put! to (cs/complete-sync-response new-state)))
|
(recur)
|
||||||
(println "Invalid msg:" msg))
|
(remove-watch state client-id)))))
|
||||||
(recur))
|
|
||||||
(remove-watch state client-id))))))
|
|
||||||
|
|
||||||
(defn init [_to-db grubs recipes]
|
(defn init [_to-db grubs recipes]
|
||||||
(reset! state (initial-state grubs recipes))
|
(reset! state (initial-state grubs recipes))
|
||||||
|
|
|
@ -7,46 +7,31 @@
|
||||||
[cljs.core.async.macros :refer [go go-loop]]))
|
[cljs.core.async.macros :refer [go go-loop]]))
|
||||||
|
|
||||||
(def app-state (atom cs/empty-state))
|
(def app-state (atom cs/empty-state))
|
||||||
(def client-shadow (atom cs/empty-state))
|
|
||||||
|
|
||||||
(defn sync-local-changes [to-remote state*]
|
|
||||||
(let [client-shadow* @client-shadow]
|
|
||||||
(when (not= state* client-shadow*)
|
|
||||||
(let [diff (sync/diff-states client-shadow* state*)
|
|
||||||
msg {:type :diff
|
|
||||||
:diff diff
|
|
||||||
:hash (hasch/uuid state*)
|
|
||||||
:shadow-hash (hasch/uuid client-shadow*)}]
|
|
||||||
(logs "Sync because:")
|
|
||||||
(logs "Server = " client-shadow*)
|
|
||||||
(logs "Client = " state*)
|
|
||||||
(logs "Diff:" diff)
|
|
||||||
(logs "Send" (hasch/uuid client-shadow*) "->" (hasch/uuid state*))
|
|
||||||
;; TODO: reset client shadow only if send succeeds
|
|
||||||
(a/put! to-remote msg)
|
|
||||||
(reset! client-shadow state*)))))
|
|
||||||
|
|
||||||
(defn sync-state! [to from]
|
(defn sync-state! [to from]
|
||||||
(go-loop []
|
(let [client-shadow (atom cs/empty-state)]
|
||||||
(when-let [{:keys [type diff hash shadow-hash] :as msg} (<! to)]
|
(add-watch app-state :app-state (fn [_ _ _ new]
|
||||||
(condp = type
|
(when-let [msg (cs/diff-states new @client-shadow)]
|
||||||
:diff (do
|
(a/put! from msg)
|
||||||
(logs "Received server diff:" shadow-hash "->" hash)
|
;; TODO: reset shadow only if send succeeds
|
||||||
(logs "Before shadow:" (hasch/uuid @client-shadow) @client-shadow)
|
(reset! client-shadow new))))
|
||||||
(if (= (hasch/uuid @client-shadow) shadow-hash)
|
(go-loop []
|
||||||
(log "Before hash check: good")
|
(when-let [{:keys [type diff hash shadow-hash] :as msg} (<! to)]
|
||||||
(log "Before hash check: FAIL"))
|
(condp = type
|
||||||
(let [new-shadow (swap! client-shadow #(sync/patch-state % diff))
|
:diff (do
|
||||||
new-state (swap! app-state #(sync/patch-state % diff))]
|
;(logs "Received server diff:" shadow-hash "->" hash)
|
||||||
(logs "After shadow:" (hasch/uuid @client-shadow) @client-shadow)
|
;(logs "Before shadow:" (hasch/uuid @client-shadow) @client-shadow)
|
||||||
(if (= (hasch/uuid new-shadow) hash)
|
(if (= (hasch/uuid @client-shadow) shadow-hash)
|
||||||
(log "After hash check: good")
|
(log "Before hash check: good")
|
||||||
(log "After hash check: FAIL"))))
|
(log "Before hash check: FAIL"))
|
||||||
:complete (do (log "Received complete sync, reset state")
|
(let [new-shadow (swap! client-shadow #(sync/patch-state % diff))
|
||||||
(logs msg)
|
new-state (swap! app-state #(sync/patch-state % diff))]
|
||||||
(reset! client-shadow (:state msg))
|
;(logs "After shadow:" (hasch/uuid @client-shadow) @client-shadow)
|
||||||
(reset! app-state (:state msg)))
|
(if (= (hasch/uuid new-shadow) hash)
|
||||||
(logs "Invalid msg:" msg))
|
(log "After hash check: good")
|
||||||
(recur)))
|
(log "After hash check: FAIL"))))
|
||||||
(add-watch app-state :app-state (fn [k ref old new] (sync-local-changes from new)))
|
:complete (do (reset! client-shadow (:state msg))
|
||||||
(a/put! from cs/complete-sync-request))
|
(reset! app-state (:state msg)))
|
||||||
|
(logs "Invalid msg:" msg))
|
||||||
|
(recur)))
|
||||||
|
(a/put! from cs/complete-sync-request)))
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
(defn send-pending-msg [websocket]
|
(defn send-pending-msg [websocket]
|
||||||
(when (and (.isOpen websocket)
|
(when (and (.isOpen websocket)
|
||||||
(not (nil? @pending-msg)))
|
(not (nil? @pending-msg)))
|
||||||
(.send websocket @pending-msg)
|
(.send websocket (pr-str @pending-msg))
|
||||||
(reset! pending-msg nil)))
|
(reset! pending-msg nil)))
|
||||||
|
|
||||||
(defn on-connected [websocket event]
|
(defn on-connected [websocket event]
|
||||||
|
|
31
src/cljx/grub/common_state.cljx
Normal file
31
src/cljx/grub/common_state.cljx
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
(ns grub.common-state
|
||||||
|
(:require [grub.sync :as sync]
|
||||||
|
[hasch.core :as hasch]))
|
||||||
|
|
||||||
|
(def empty-state {:grubs {} :recipes {}})
|
||||||
|
|
||||||
|
(def complete-sync-request {:type :complete})
|
||||||
|
(defn complete-sync-response [state]
|
||||||
|
{:type :complete
|
||||||
|
:state state})
|
||||||
|
|
||||||
|
(defn diff-msg [diff hash shadow-hash]
|
||||||
|
{:type :diff
|
||||||
|
:diff diff
|
||||||
|
:hash hash
|
||||||
|
:shadow-hash shadow-hash})
|
||||||
|
|
||||||
|
(defn diff-states [state shadow*]
|
||||||
|
(let [shadow shadow*]
|
||||||
|
(when (not= state shadow)
|
||||||
|
(let [diff (sync/diff-states shadow state)
|
||||||
|
hash (hasch/uuid state)
|
||||||
|
shadow-hash (hasch/uuid shadow)
|
||||||
|
msg (diff-msg diff hash shadow-hash)]
|
||||||
|
msg
|
||||||
|
;(logs "Sync because:")
|
||||||
|
;(logs "Local = " state)
|
||||||
|
;(logs "Remote = " shadow)
|
||||||
|
;(logs "Diff:" diff)
|
||||||
|
;(logs "Send" shadow-hash "->" hash)
|
||||||
|
))))
|
Loading…
Add table
Reference in a new issue