Switch to Datomic for storage (not persistent)
- Still not taking advantage of Datomic features but using it as a simple dump for Clojure data structures.
This commit is contained in:
parent
fdd9baf23b
commit
c1e0dfbf0b
5 changed files with 135 additions and 45 deletions
53
database_schema.edn
Normal file
53
database_schema.edn
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
[
|
||||||
|
;; grubs
|
||||||
|
{:db/id #db/id[:db.part/db]
|
||||||
|
:db/ident :grub/id
|
||||||
|
:db/valueType :db.type/keyword
|
||||||
|
:db/cardinality :db.cardinality/one
|
||||||
|
:db/unique :db.unique/identity
|
||||||
|
:db/doc "Grub ID"
|
||||||
|
:db.install/_attribute :db.part/db}
|
||||||
|
{:db/id #db/id[:db.part/db]
|
||||||
|
:db/ident :grub/text
|
||||||
|
:db/valueType :db.type/string
|
||||||
|
:db/cardinality :db.cardinality/one
|
||||||
|
:db/fulltext true
|
||||||
|
:db/doc "The text of a grub item e.g. '3 apples'"
|
||||||
|
:db.install/_attribute :db.part/db}
|
||||||
|
{:db/id #db/id[:db.part/db]
|
||||||
|
:db/ident :grub/completed
|
||||||
|
:db/valueType :db.type/boolean
|
||||||
|
:db/cardinality :db.cardinality/one
|
||||||
|
:db/doc "The status of a grub item (completed or not completed)"
|
||||||
|
:db.install/_attribute :db.part/db}
|
||||||
|
|
||||||
|
;; recipes
|
||||||
|
{:db/id #db/id[:db.part/db]
|
||||||
|
:db/ident :recipe/id
|
||||||
|
:db/valueType :db.type/keyword
|
||||||
|
:db/cardinality :db.cardinality/one
|
||||||
|
:db/unique :db.unique/identity
|
||||||
|
:db/doc "Recipe ID"
|
||||||
|
:db.install/_attribute :db.part/db}
|
||||||
|
{:db/id #db/id[:db.part/db]
|
||||||
|
:db/ident :recipe/name
|
||||||
|
:db/valueType :db.type/string
|
||||||
|
:db/cardinality :db.cardinality/one
|
||||||
|
:db/fulltext true
|
||||||
|
:db/doc "Recipe name"
|
||||||
|
:db.install/_attribute :db.part/db}
|
||||||
|
{:db/id #db/id[:db.part/db]
|
||||||
|
:db/ident :recipe/grubs
|
||||||
|
:db/valueType :db.type/string
|
||||||
|
:db/cardinality :db.cardinality/one
|
||||||
|
:db/fulltext true
|
||||||
|
:db/doc "Recipe ingredients"
|
||||||
|
:db.install/_attribute :db.part/db}
|
||||||
|
{:db/id #db/id[:db.part/db]
|
||||||
|
:db/ident :recipe/directions
|
||||||
|
:db/valueType :db.type/string
|
||||||
|
:db/cardinality :db.cardinality/one
|
||||||
|
:db/fulltext true
|
||||||
|
:db/doc "Directions for making a recipe"
|
||||||
|
:db.install/_attribute :db.part/db}
|
||||||
|
]
|
|
@ -16,7 +16,10 @@
|
||||||
[sablono "0.3.4"]
|
[sablono "0.3.4"]
|
||||||
[cljs-uuid "0.0.4"]
|
[cljs-uuid "0.0.4"]
|
||||||
[com.cognitect/transit-clj "0.8.275"]
|
[com.cognitect/transit-clj "0.8.275"]
|
||||||
[com.cognitect/transit-cljs "0.8.220"]]
|
[com.cognitect/transit-cljs "0.8.220"]
|
||||||
|
[com.datomic/datomic-pro "0.9.5173" :exclusions [com.fasterxml.jackson.core/jackson-annotations]]]
|
||||||
|
:repositories {"my.datomic.com" {:url "https://my.datomic.com/repo"
|
||||||
|
:creds :gpg}}
|
||||||
:profiles {:uberjar {:aot :all}
|
:profiles {:uberjar {:aot :all}
|
||||||
:dev {:source-paths ["dev"]
|
:dev {:source-paths ["dev"]
|
||||||
:dependencies [[org.clojure/tools.namespace "0.2.10"]
|
:dependencies [[org.clojure/tools.namespace "0.2.10"]
|
||||||
|
|
|
@ -39,8 +39,7 @@
|
||||||
|
|
||||||
(def prod-system
|
(def prod-system
|
||||||
{:index prod-index-page
|
{:index prod-index-page
|
||||||
:db-name "grub"
|
:database-uri "datomic:mem://grub"
|
||||||
:db nil
|
|
||||||
:db-conn nil
|
:db-conn nil
|
||||||
:port 3000
|
:port 3000
|
||||||
:stop-server nil
|
:stop-server nil
|
||||||
|
@ -48,8 +47,7 @@
|
||||||
|
|
||||||
(def dev-system
|
(def dev-system
|
||||||
{:index dev-index-page
|
{:index dev-index-page
|
||||||
:db-name "grub-dev"
|
:database-uri "datomic:mem://grub"
|
||||||
:db nil
|
|
||||||
:db-conn nil
|
:db-conn nil
|
||||||
:port 3000
|
:port 3000
|
||||||
:stop-server nil
|
:stop-server nil
|
||||||
|
@ -92,22 +90,21 @@
|
||||||
(handle-websocket states new-states-pub)
|
(handle-websocket states new-states-pub)
|
||||||
(wrap-bounce-favicon)))
|
(wrap-bounce-favicon)))
|
||||||
|
|
||||||
(defn start [{:keys [port db-name states] :as system}]
|
(defn start [{:keys [port database-uri states] :as system}]
|
||||||
(let [{:keys [db conn]} (db/connect db-name)
|
(let [db-conn (db/connect database-uri)
|
||||||
new-states (chan)
|
new-states (chan)
|
||||||
new-states-pub (a/pub new-states (fn [_] :new-state))
|
new-states-pub (a/pub new-states (fn [_] :new-state))
|
||||||
db-state (db/get-current-state db)
|
db-state (db/get-current-state db-conn)
|
||||||
_ (reset! states (state/new-states (if db-state db-state state/empty-state)))
|
_ (reset! states (state/new-states (if db-state db-state state/empty-state)))
|
||||||
stop-server (httpkit/run-server (make-handler system new-states-pub) {:port port})]
|
stop-server (httpkit/run-server (make-handler system new-states-pub) {:port port})]
|
||||||
(add-watch states :db (fn [_ _ old new]
|
(add-watch states :db (fn [_ _ old new]
|
||||||
(when-not (= old new)
|
(when-not (= old new)
|
||||||
(let [new-state (state/get-latest new)]
|
(let [new-state (state/get-latest new)]
|
||||||
(a/put! new-states new-state)
|
(a/put! new-states new-state)
|
||||||
(db/update-db! db new-state)))))
|
(db/update-db! db-conn new-state)))))
|
||||||
(println "Started server on localhost:" port)
|
(println "Started server on localhost:" port)
|
||||||
(assoc system
|
(assoc system
|
||||||
:db db
|
:db-conn db-conn
|
||||||
:db-conn conn
|
|
||||||
:stop-server stop-server
|
:stop-server stop-server
|
||||||
:states states)))
|
:states states)))
|
||||||
|
|
||||||
|
@ -149,7 +146,7 @@
|
||||||
(println "options:" options)
|
(println "options:" options)
|
||||||
(cond
|
(cond
|
||||||
(:help options) (exit 0 (usage summary))
|
(:help options) (exit 0 (usage summary))
|
||||||
(not= (count arguments) 1) (exit 1 (usage summary))
|
(not= (count arguments) 2) (exit 1 (usage summary))
|
||||||
errors (exit 1 (error-msg errors)))
|
errors (exit 1 (error-msg errors)))
|
||||||
(case (first arguments)
|
(case (first arguments)
|
||||||
"development" (start (merge dev-system options))
|
"development" (start (merge dev-system options))
|
||||||
|
|
|
@ -1,34 +1,71 @@
|
||||||
(ns grub.db
|
(ns grub.db
|
||||||
(:require [datomic.api :as d :refer [q db]]
|
(:require [datomic.api :as d]
|
||||||
clojure.pprint
|
[clojure.core.async :as a :refer [<! >! chan go]]
|
||||||
[monger.core :as m]
|
[grub.util :as util]))
|
||||||
[monger.collection :as mc]
|
|
||||||
[clojure.core.async :as a :refer [<! >! chan go]]))
|
|
||||||
|
|
||||||
;(def uri "datomic:mem://seattle")
|
(def schema-tx (read-string (slurp "database_schema.edn")))
|
||||||
;(d/create-database uri)
|
|
||||||
|
|
||||||
|
(defn create-db [uri]
|
||||||
|
(d/create-database uri)
|
||||||
|
(let [conn (d/connect uri)]
|
||||||
|
@(d/transact conn schema-tx)))
|
||||||
|
|
||||||
(def collection "grub-lists")
|
(defn connect [uri]
|
||||||
|
(create-db uri)
|
||||||
|
(let [conn (d/connect uri)]
|
||||||
|
(println "Connected to datomic at " uri)
|
||||||
|
conn))
|
||||||
|
|
||||||
(defn clear-all [db]
|
(defn map-keys [key-maps coll]
|
||||||
(mc/drop db collection))
|
(reduce (fn [new-coll [key new-key]] (assoc new-coll new-key (get coll key))) {} key-maps))
|
||||||
|
|
||||||
(defn update-db! [db state]
|
(defn get-current-state [conn]
|
||||||
(mc/drop db collection)
|
(let [db (d/db conn)
|
||||||
(mc/insert db collection state))
|
get-entity (fn [[id]] (d/touch (d/entity db id)))
|
||||||
|
grub-ids (d/q '[:find ?g :where [?g :grub/id]] (d/db conn))
|
||||||
|
map-grub-keys #(map-keys {:grub/id :id :grub/text :text :grub/completed :completed} %)
|
||||||
|
grubs (->> grub-ids
|
||||||
|
(map (comp map-grub-keys get-entity))
|
||||||
|
vec
|
||||||
|
(util/map-by-key :id))
|
||||||
|
recipe-ids (d/q '[:find ?r :where [?r :recipe/id]] (d/db conn))
|
||||||
|
map-recipe-keys #(map-keys {:recipe/id :id :recipe/name :name :recipe/grubs :grubs :recipe/directions :directions} %)
|
||||||
|
recipes (->> recipe-ids
|
||||||
|
(map (comp map-recipe-keys get-entity))
|
||||||
|
vec
|
||||||
|
(util/map-by-key :id))]
|
||||||
|
{:grubs grubs
|
||||||
|
:recipes recipes}))
|
||||||
|
|
||||||
(defn get-current-state [db]
|
(defn grub-tx [grub]
|
||||||
(let [state (first (mc/find-maps db collection))]
|
[{:db/id (d/tempid :db.part/user)
|
||||||
(when state
|
:grub/id (:id grub)
|
||||||
(dissoc state :_id))))
|
:grub/text (:text grub)
|
||||||
|
:grub/completed (:completed grub)}])
|
||||||
|
|
||||||
(defn connect [db-name]
|
(defn recipe-tx [recipe]
|
||||||
(let [conn (m/connect)
|
[{:db/id (d/tempid :db.part/user)
|
||||||
db (m/get-db conn db-name)]
|
:recipe/id (:id recipe)
|
||||||
(println "Connected to mongo at localhost:" db-name)
|
:recipe/name (:name recipe)
|
||||||
{:conn conn
|
:recipe/grubs (:grubs recipe)
|
||||||
:db db}))
|
:recipe/directions (:directions recipe)}])
|
||||||
|
|
||||||
|
(defn update-db! [conn state]
|
||||||
|
(let [grubs-tx (->> state
|
||||||
|
:grubs
|
||||||
|
(vals)
|
||||||
|
(map grub-tx)
|
||||||
|
(flatten)
|
||||||
|
(vec))
|
||||||
|
recipes-tx (->> state
|
||||||
|
:recipes
|
||||||
|
(vals)
|
||||||
|
(map recipe-tx)
|
||||||
|
(flatten)
|
||||||
|
(vec))
|
||||||
|
tx (into grubs-tx recipes-tx)]
|
||||||
|
@(d/transact conn tx)))
|
||||||
|
|
||||||
(defn disconnect [conn]
|
(defn disconnect [conn]
|
||||||
(m/disconnect conn))
|
(d/release conn))
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
(ns grub.util
|
(ns grub.util
|
||||||
(:require #+clj [clojure.core.async :as a :refer [<! >! chan go]]
|
(:require #?(:clj [clojure.core.async :as a :refer [<! >! chan go]]
|
||||||
#+cljs [cljs.core.async :as a :refer [<! >! chan]])
|
:cljs [cljs.core.async :as a :refer [<! >! chan]]))
|
||||||
#+cljs (:require-macros [grub.macros :refer [log logs]]
|
#?(:cljs (:require-macros [grub.macros :refer [log logs]]
|
||||||
[cljs.core.async.macros :refer [go]]))
|
[cljs.core.async.macros :refer [go]])))
|
||||||
|
|
||||||
(defn map-by-key [key coll]
|
(defn map-by-key [key coll]
|
||||||
(->> coll
|
(->> coll
|
||||||
|
@ -11,11 +11,11 @@
|
||||||
|
|
||||||
(defn printer []
|
(defn printer []
|
||||||
(let [in (chan)]
|
(let [in (chan)]
|
||||||
(go (loop []
|
(go (loop []
|
||||||
(when-let [msg (<! printer)]
|
(when-let [msg (<! printer)]
|
||||||
#+clj (clojure.pprint/pprint msg)
|
#?(:clj (do (clojure.pprint/pprint msg)
|
||||||
#+clj (println "-------")
|
(println "-------"))
|
||||||
#+cljs (logs msg)
|
:cljs (do (logs msg)
|
||||||
#+cljs (log "-------")
|
(log "-------")) )
|
||||||
(recur))))))
|
(recur))))))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue