diff --git a/src/clj/grub/state.clj b/src/clj/grub/state.clj index 1b4b2ef..61ebe5a 100644 --- a/src/clj/grub/state.clj +++ b/src/clj/grub/state.clj @@ -14,52 +14,35 @@ {:grubs (util/map-by-key :id grubs) :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] (let [client-id (java.util.UUID/randomUUID) server-shadow (atom cs/empty-state)] - (add-watch state client-id (fn [k ref old new] - (sync-remote-changes to new server-shadow))) + (add-watch state client-id (fn [_ _ _ new-state] + (when-let [msg (cs/diff-states new-state server-shadow)] + (a/put! to msg) + (reset! server-shadow new-state)))) (a/go-loop [] - (let [{:keys [type diff hash shadow-hash] :as msg} (" hash) - (println "Before shadow:" (hasch/uuid @server-shadow) @server-shadow) - (if (= (hasch/uuid @server-shadow) shadow-hash) - (println "Before hash check: good") - (println "Before hash check: FAIL")) - (let [new-shadow (swap! server-shadow #(sync/patch-state % diff)) - new-state (swap! state #(sync/patch-state % diff))] - ;; TODO: check if hashes match - (println "After shadow:" (hasch/uuid new-shadow) new-shadow) - (if (= (hasch/uuid new-shadow) hash) - (println "After hash check: good") - (println "After hash check: FAIL")) - (>! @to-db diff))) - :complete (let [new-state (reset! server-shadow @state)] - (a/put! to (cs/complete-sync-response new-state))) - (println "Invalid msg:" msg)) - (recur)) - (remove-watch state client-id)))))) + (when-let [{:keys [type diff hash shadow-hash] :as msg} (" hash) + (println "Before shadow:" (hasch/uuid @server-shadow) @server-shadow) + (if (= (hasch/uuid @server-shadow) shadow-hash) + (println "Before hash check: good") + (println "Before hash check: FAIL")) + (let [new-shadow (swap! server-shadow #(sync/patch-state % diff)) + new-state (swap! state #(sync/patch-state % diff))] + ;; TODO: check if hashes match + (println "After shadow:" (hasch/uuid new-shadow) new-shadow) + (if (= (hasch/uuid new-shadow) hash) + (println "After hash check: good") + (println "After hash check: FAIL")) + (>! @to-db diff))) + :complete (let [new-state (reset! server-shadow @state)] + (a/put! to (cs/complete-sync-response new-state))) + (println "Invalid msg:" msg)) + (recur) + (remove-watch state client-id))))) (defn init [_to-db grubs recipes] (reset! state (initial-state grubs recipes)) diff --git a/src/cljs/grub/state.cljs b/src/cljs/grub/state.cljs index 1daad00..0deac20 100644 --- a/src/cljs/grub/state.cljs +++ b/src/cljs/grub/state.cljs @@ -7,46 +7,31 @@ [cljs.core.async.macros :refer [go go-loop]])) (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] - (go-loop [] - (when-let [{:keys [type diff hash shadow-hash] :as msg} (" hash) - (logs "Before shadow:" (hasch/uuid @client-shadow) @client-shadow) - (if (= (hasch/uuid @client-shadow) shadow-hash) - (log "Before hash check: good") - (log "Before hash check: FAIL")) - (let [new-shadow (swap! client-shadow #(sync/patch-state % diff)) - new-state (swap! app-state #(sync/patch-state % diff))] - (logs "After shadow:" (hasch/uuid @client-shadow) @client-shadow) - (if (= (hasch/uuid new-shadow) hash) - (log "After hash check: good") - (log "After hash check: FAIL")))) - :complete (do (log "Received complete sync, reset state") - (logs msg) - (reset! client-shadow (:state msg)) - (reset! app-state (:state msg))) - (logs "Invalid msg:" msg)) - (recur))) - (add-watch app-state :app-state (fn [k ref old new] (sync-local-changes from new))) - (a/put! from cs/complete-sync-request)) + (let [client-shadow (atom cs/empty-state)] + (add-watch app-state :app-state (fn [_ _ _ new] + (when-let [msg (cs/diff-states new @client-shadow)] + (a/put! from msg) + ;; TODO: reset shadow only if send succeeds + (reset! client-shadow new)))) + (go-loop [] + (when-let [{:keys [type diff hash shadow-hash] :as msg} (" hash) + ;(logs "Before shadow:" (hasch/uuid @client-shadow) @client-shadow) + (if (= (hasch/uuid @client-shadow) shadow-hash) + (log "Before hash check: good") + (log "Before hash check: FAIL")) + (let [new-shadow (swap! client-shadow #(sync/patch-state % diff)) + new-state (swap! app-state #(sync/patch-state % diff))] + ;(logs "After shadow:" (hasch/uuid @client-shadow) @client-shadow) + (if (= (hasch/uuid new-shadow) hash) + (log "After hash check: good") + (log "After hash check: FAIL")))) + :complete (do (reset! client-shadow (:state msg)) + (reset! app-state (:state msg))) + (logs "Invalid msg:" msg)) + (recur))) + (a/put! from cs/complete-sync-request))) diff --git a/src/cljs/grub/websocket.cljs b/src/cljs/grub/websocket.cljs index 56455bd..1756418 100644 --- a/src/cljs/grub/websocket.cljs +++ b/src/cljs/grub/websocket.cljs @@ -16,7 +16,7 @@ (defn send-pending-msg [websocket] (when (and (.isOpen websocket) (not (nil? @pending-msg))) - (.send websocket @pending-msg) + (.send websocket (pr-str @pending-msg)) (reset! pending-msg nil))) (defn on-connected [websocket event] diff --git a/src/cljx/grub/common_state.cljx b/src/cljx/grub/common_state.cljx new file mode 100644 index 0000000..9d896a6 --- /dev/null +++ b/src/cljx/grub/common_state.cljx @@ -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) + ))))