From 1b8339dec006f9e82453e9378569a8d23a5859ed Mon Sep 17 00:00:00 2001 From: Nicholas Kariniemi Date: Mon, 22 Sep 2014 22:47:36 +0300 Subject: [PATCH] Mid-changes: organize state changes --- src/clj/grub/state.clj | 193 ++++++++++++++++++++++++----------------- 1 file changed, 113 insertions(+), 80 deletions(-) diff --git a/src/clj/grub/state.clj b/src/clj/grub/state.clj index df433dc..0901cb3 100644 --- a/src/clj/grub/state.clj +++ b/src/clj/grub/state.clj @@ -5,19 +5,21 @@ [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 initial-state [grubs recipes] + [{:grubs (util/map-by-key :id grubs) + :recipes (util/map-by-key :id recipes)}]) + +(def states (ref [])) (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) +(defn add-history-state [states new-state] + (let [{:keys [state hash]} (first states) new-hash (hasch/uuid new-state)] (if (= hash new-hash) - current - (conj current {:hash hash :state state})))) + states + (conj states {:hash hash :state state})))) (defn receive-diff [states diff shadow-hash] (let [state (:state (first states)) @@ -30,84 +32,115 @@ :new-shadow state :full-sync? true}))) +(defn apply-diff? [states diff shadow-hash] + (get-history-state states shadow-hash)) - -(def state (atom cs/empty-state)) (def to-db (atom nil)) -(def to-all (chan)) -(def from-all (a/mult to-all)) -(def state-history (atom [])) +(defn make-client [in client-state states] + (let [out (chan) + full-sync! (fn [] (let [new-client (dosync (ref-set client-state @states))] + (a/put! out (cs/complete-sync-response new-client))))] + (a/go-loop + [] + (when-let [{:keys [type diff shadow-hash state]} (client ! @to-db diff)) - (do (log "Applying diff failed --> full sync") - (let [sync-state @state] - (reset! client-state sync-state) - (a/put! to (cs/complete-sync-response sync-state)))))) - ;; We have something different than they thought - ;; Check history - (do - (log "Hash check failed --> Reset from history") - (if-let [history-state (get-history-state shadow-hash)] - ;; Found what they thought we had in history, - ;; reset client state to this and continue as normal - (do - (reset! client-state history-state) - (let [new-shadow (swap! client-state diff/patch-state diff)] - (if (= (hasch/uuid new-shadow) hash) - (let [new-state (swap! state diff/patch-state diff)] - (>! @to-db diff)) - (do (log "Applying diff failed --> full sync") - (let [sync-state @state] - (reset! client-state sync-state) - (a/put! to (cs/complete-sync-response sync-state))))))) - ;; Not found in history, do complete sync - (do (log "Hash check failed, not in history --> full sync") - (let [sync-state @state] - (reset! client-state sync-state) - (a/put! to (cs/complete-sync-response sync-state))))))) - :complete (let [new-state (reset! client-state @state)] - (log "full sync") - (a/put! to (cs/complete-sync-response new-state))) - (log "Invalid msg:" msg)) - (recur)) - (remove-watch state client-id))))) + state-changes (chan) + events (chan) + client-state (ref cs/empty-state)] + (add-watch states client-id (fn [_ _ _ [state _]] (a/put! state-changes state))) + (a/pipe (a/merge ! >client v) + (recur)) + (remove-watch states client-id)))) + + ;; (let [full-sync! (fn [] (let [new-client (dosync (ref-set client-state @states))] + ;; (a/put! >client (cs/complete-sync-response new-client))))] + ;; (a/go-loop + ;; [] + ;; (if-let [{:keys [type diff shadow-hash state]} (client (diff/diff-states @client-state (first @states))) + ;; :diff (dosync + ;; (let [state (:state (first @states)) + ;; shadow (get-history-state states shadow-hash)] + ;; (if shadow + ;; (do (alter states add-history-state (diff/patch-state state diff)) + ;; (alter client-state diff/patch-state shadow diff)) + ;; (full-sync!)))) + ;; :full-sync (full-sync!)) + ;; (remove-watch states client-id)))) + )) + +;; (defn sync-new-client! [to from] +;; (let [client-id (java.util.UUID/randomUUID) +;; state-changes (chan)] +;; (add-watch states client-id (fn [_ _ _ [current-state _]] +;; (put! state-changes current-state))) +;; (a/go-loop [client-state cs/empty-state] +;; (if-let [[{:keys [type] :as msg} c] (! @to-db diff)) +;; (do (log "Applying diff failed --> full sync") +;; (let [sync-state @state] +;; (reset! client-state sync-state) +;; (a/put! to (cs/complete-sync-response sync-state)))))) +;; ;; We have something different than they thought +;; ;; Check history +;; (do +;; (log "Hash check failed --> Reset from history") +;; (if-let [history-state (get-history-state shadow-hash)] +;; ;; Found what they thought we had in history, +;; ;; reset client state to this and continue as normal +;; (do +;; (reset! client-state history-state) +;; (let [new-shadow (swap! client-state diff/patch-state diff)] +;; (if (= (hasch/uuid new-shadow) hash) +;; (let [new-state (swap! state diff/patch-state diff)] +;; (>! @to-db diff)) +;; (do (log "Applying diff failed --> full sync") +;; (let [sync-state @state] +;; (reset! client-state sync-state) +;; (a/put! to (cs/complete-sync-response sync-state))))))) +;; ;; Not found in history, do complete sync +;; (do (log "Hash check failed, not in history --> full sync") +;; (let [sync-state @state] +;; (reset! client-state sync-state) +;; (a/put! to (cs/complete-sync-response sync-state))))))) +;; :complete (let [new-state (reset! client-state @state)] +;; (log "full sync") +;; (a/put! to (cs/complete-sync-response new-state))) +;; (log "Invalid msg:" msg)) +;; (recur)) +;; (remove-watch state client-id))))) (defn init [_to-db grubs recipes] - (reset! state (initial-state grubs recipes)) + (reset! states (initial-state grubs recipes)) (reset! to-db _to-db))