Simplify MongoDB code by just storing whole state
- Every time it receives a state, it blows away the existing one and puts in the new one. - There's a non-zero probability of losing the entire state if the server fails after blowing away the previous state and before inserting the new.
This commit is contained in:
parent
48ba2c5449
commit
86bfdf80e4
4 changed files with 21 additions and 51 deletions
|
@ -73,14 +73,14 @@
|
||||||
(reset! index-page prod-index-page)
|
(reset! index-page prod-index-page)
|
||||||
(let [to-db (chan)]
|
(let [to-db (chan)]
|
||||||
(db/connect-production-database to-db mongo-url)
|
(db/connect-production-database to-db mongo-url)
|
||||||
(state/init-server to-db (db/get-current-grubs) (db/get-current-recipes))
|
(state/init-server to-db (db/get-current-state))
|
||||||
(println "Starting production server on localhost:" port)
|
(println "Starting production server on localhost:" port)
|
||||||
(start-server port)))
|
(start-server port)))
|
||||||
|
|
||||||
(defn start-development-server [{:keys [port]}]
|
(defn start-development-server [{:keys [port]}]
|
||||||
(let [to-db (chan)]
|
(let [to-db (chan)]
|
||||||
(db/connect-development-database to-db)
|
(db/connect-development-database to-db)
|
||||||
(state/init-server to-db (db/get-current-grubs) (db/get-current-recipes))
|
(state/init-server to-db (db/get-current-state))
|
||||||
(println "Starting development server on localhost:" port)
|
(println "Starting development server on localhost:" port)
|
||||||
(start-server port)))
|
(start-server port)))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns grub.db
|
(ns grub.db
|
||||||
(:require [grub.util :as util]
|
(:require [grub.util :as util]
|
||||||
|
[grub.sync :as sync]
|
||||||
[monger.core :as m]
|
[monger.core :as m]
|
||||||
[monger.collection :as mc]
|
[monger.collection :as mc]
|
||||||
[monger.operators :as mo]
|
[monger.operators :as mo]
|
||||||
|
@ -7,54 +8,22 @@
|
||||||
|
|
||||||
(def conn (atom nil))
|
(def conn (atom nil))
|
||||||
(def db (atom nil))
|
(def db (atom nil))
|
||||||
(def grub-collection "grubs")
|
(def collection "grub-lists")
|
||||||
(def recipe-collection "recipes")
|
|
||||||
(def production-db "grub")
|
(def production-db "grub")
|
||||||
(def development-db "grub-dev")
|
(def development-db "grub-dev")
|
||||||
|
|
||||||
(defn clear-grubs []
|
|
||||||
(mc/drop @db grub-collection))
|
|
||||||
|
|
||||||
(defn clear-recipes []
|
|
||||||
(mc/drop @db recipe-collection))
|
|
||||||
|
|
||||||
(defn clear-all []
|
(defn clear-all []
|
||||||
(clear-grubs)
|
(mc/drop @db collection))
|
||||||
(clear-recipes))
|
|
||||||
|
|
||||||
(defn update-db! [{:keys [grubs recipes]}]
|
(defn update-db! [state]
|
||||||
(let [deleted-grubs (:deleted grubs)
|
(mc/drop @db collection)
|
||||||
updated-grubs (->> (:updated grubs)
|
(mc/insert @db collection state))
|
||||||
(seq)
|
|
||||||
(map (fn [[k v]]
|
|
||||||
(-> v
|
|
||||||
(dissoc :id)
|
|
||||||
(assoc :_id k)))))
|
|
||||||
deleted-recipes (:deleted recipes)
|
|
||||||
updated-recipes (->> (:updated recipes)
|
|
||||||
(seq)
|
|
||||||
(map (fn [[k v]]
|
|
||||||
(-> v
|
|
||||||
(dissoc :id)
|
|
||||||
(assoc :_id k)))))]
|
|
||||||
(doseq [g deleted-grubs]
|
|
||||||
(mc/remove-by-id @db grub-collection g))
|
|
||||||
(doseq [g updated-grubs]
|
|
||||||
(mc/update-by-id @db grub-collection (:_id g) g {:upsert true}))
|
|
||||||
(doseq [r deleted-recipes]
|
|
||||||
(mc/remove-by-id @db recipe-collection r))
|
|
||||||
(doseq [r updated-recipes]
|
|
||||||
(mc/update-by-id @db recipe-collection (:_id r) r {:upsert true}))))
|
|
||||||
|
|
||||||
(defn get-current-grubs []
|
(defn get-current-state []
|
||||||
(->> (mc/find-maps @db grub-collection)
|
(let [state (first (mc/find-maps @db collection))]
|
||||||
(sort-by :_id)
|
(if state
|
||||||
(map #(clojure.set/rename-keys % {:_id :id}))))
|
(dissoc state :_id)
|
||||||
|
sync/empty-state)))
|
||||||
(defn get-current-recipes []
|
|
||||||
(->> (mc/find-maps @db recipe-collection)
|
|
||||||
(sort-by :_id)
|
|
||||||
(map #(clojure.set/rename-keys % {:_id :id}))))
|
|
||||||
|
|
||||||
(defn connect! [db-name mongo-url]
|
(defn connect! [db-name mongo-url]
|
||||||
(if mongo-url
|
(if mongo-url
|
||||||
|
@ -65,8 +34,9 @@
|
||||||
|
|
||||||
(defn connect-and-handle-events [to-db db-name & [mongo-url]]
|
(defn connect-and-handle-events [to-db db-name & [mongo-url]]
|
||||||
(a/go-loop []
|
(a/go-loop []
|
||||||
(if-let [diff (<! to-db)]
|
(if-let [state (<! to-db)]
|
||||||
(do (update-db! diff)
|
(do (println "DB got new state")
|
||||||
|
(update-db! state)
|
||||||
(recur))
|
(recur))
|
||||||
(println "Database disconnected")))
|
(println "Database disconnected")))
|
||||||
(let [_conn (connect! db-name mongo-url)]
|
(let [_conn (connect! db-name mongo-url)]
|
||||||
|
|
|
@ -65,7 +65,6 @@
|
||||||
(def states (atom []))
|
(def states (atom []))
|
||||||
(def empty-state sync/empty-state)
|
(def empty-state sync/empty-state)
|
||||||
|
|
||||||
;; TODO: Remove watch, close up channels properly
|
|
||||||
#+clj
|
#+clj
|
||||||
(defn sync-new-client! [>client <client]
|
(defn sync-new-client! [>client <client]
|
||||||
(let [client-id (java.util.UUID/randomUUID)
|
(let [client-id (java.util.UUID/randomUUID)
|
||||||
|
@ -85,8 +84,9 @@
|
||||||
(a/close! state-change-events)))))
|
(a/close! state-change-events)))))
|
||||||
(make-server-agent client-events >client states)))
|
(make-server-agent client-events >client states)))
|
||||||
|
|
||||||
(defn init-server [to-db grubs recipes]
|
#+clj
|
||||||
(reset! states (sync/initial-state grubs recipes))
|
(defn init-server [to-db initial-state]
|
||||||
|
(reset! states (sync/new-state initial-state))
|
||||||
(add-watch states :to-db (fn [_ _ old-states new-states]
|
(add-watch states :to-db (fn [_ _ old-states new-states]
|
||||||
(a/put! to-db (sync/get-current-state new-states)))))
|
(a/put! to-db (sync/get-current-state new-states)))))
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
(doseq [grub grubs]
|
(doseq [grub grubs]
|
||||||
(test/is (taxi/find-element driver {:value grub})
|
(test/is (taxi/find-element driver {:value grub})
|
||||||
"Previously added grubs should be loaded on refresh")))
|
"Previously added grubs should be loaded on refresh")))
|
||||||
(db/clear-grubs))
|
(db/clear-all))
|
||||||
|
|
||||||
(defn test-added-grubs-sync [url driver1 driver2]
|
(defn test-added-grubs-sync [url driver1 driver2]
|
||||||
(taxi/to driver1 url)
|
(taxi/to driver1 url)
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
(defn start-db-and-websocket-server! []
|
(defn start-db-and-websocket-server! []
|
||||||
(let [to-db (chan)]
|
(let [to-db (chan)]
|
||||||
(db/connect-and-handle-events to-db "grub-integration-test")
|
(db/connect-and-handle-events to-db "grub-integration-test")
|
||||||
(state/init-server to-db (db/get-current-grubs) (db/get-current-recipes))))
|
(state/init-server to-db (db/get-current-state))))
|
||||||
|
|
||||||
(defn run []
|
(defn run []
|
||||||
(println "Starting integration test")
|
(println "Starting integration test")
|
||||||
|
|
Loading…
Reference in a new issue