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"]
|
||||
[cljs-uuid "0.0.4"]
|
||||
[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}
|
||||
:dev {:source-paths ["dev"]
|
||||
:dependencies [[org.clojure/tools.namespace "0.2.10"]
|
||||
|
|
|
@ -39,8 +39,7 @@
|
|||
|
||||
(def prod-system
|
||||
{:index prod-index-page
|
||||
:db-name "grub"
|
||||
:db nil
|
||||
:database-uri "datomic:mem://grub"
|
||||
:db-conn nil
|
||||
:port 3000
|
||||
:stop-server nil
|
||||
|
@ -48,8 +47,7 @@
|
|||
|
||||
(def dev-system
|
||||
{:index dev-index-page
|
||||
:db-name "grub-dev"
|
||||
:db nil
|
||||
:database-uri "datomic:mem://grub"
|
||||
:db-conn nil
|
||||
:port 3000
|
||||
:stop-server nil
|
||||
|
@ -92,22 +90,21 @@
|
|||
(handle-websocket states new-states-pub)
|
||||
(wrap-bounce-favicon)))
|
||||
|
||||
(defn start [{:keys [port db-name states] :as system}]
|
||||
(let [{:keys [db conn]} (db/connect db-name)
|
||||
(defn start [{:keys [port database-uri states] :as system}]
|
||||
(let [db-conn (db/connect database-uri)
|
||||
new-states (chan)
|
||||
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)))
|
||||
stop-server (httpkit/run-server (make-handler system new-states-pub) {:port port})]
|
||||
(add-watch states :db (fn [_ _ old new]
|
||||
(when-not (= old new)
|
||||
(let [new-state (state/get-latest new)]
|
||||
(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)
|
||||
(assoc system
|
||||
:db db
|
||||
:db-conn conn
|
||||
:db-conn db-conn
|
||||
:stop-server stop-server
|
||||
:states states)))
|
||||
|
||||
|
@ -149,7 +146,7 @@
|
|||
(println "options:" options)
|
||||
(cond
|
||||
(: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)))
|
||||
(case (first arguments)
|
||||
"development" (start (merge dev-system options))
|
||||
|
|
|
@ -1,34 +1,71 @@
|
|||
(ns grub.db
|
||||
(:require [datomic.api :as d :refer [q db]]
|
||||
clojure.pprint
|
||||
[monger.core :as m]
|
||||
[monger.collection :as mc]
|
||||
[clojure.core.async :as a :refer [<! >! chan go]]))
|
||||
(:require [datomic.api :as d]
|
||||
[clojure.core.async :as a :refer [<! >! chan go]]
|
||||
[grub.util :as util]))
|
||||
|
||||
;(def uri "datomic:mem://seattle")
|
||||
;(d/create-database uri)
|
||||
(def schema-tx (read-string (slurp "database_schema.edn")))
|
||||
|
||||
(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]
|
||||
(mc/drop db collection))
|
||||
(defn map-keys [key-maps coll]
|
||||
(reduce (fn [new-coll [key new-key]] (assoc new-coll new-key (get coll key))) {} key-maps))
|
||||
|
||||
(defn update-db! [db state]
|
||||
(mc/drop db collection)
|
||||
(mc/insert db collection state))
|
||||
(defn get-current-state [conn]
|
||||
(let [db (d/db conn)
|
||||
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]
|
||||
(let [state (first (mc/find-maps db collection))]
|
||||
(when state
|
||||
(dissoc state :_id))))
|
||||
(defn grub-tx [grub]
|
||||
[{:db/id (d/tempid :db.part/user)
|
||||
:grub/id (:id grub)
|
||||
:grub/text (:text grub)
|
||||
:grub/completed (:completed grub)}])
|
||||
|
||||
(defn connect [db-name]
|
||||
(let [conn (m/connect)
|
||||
db (m/get-db conn db-name)]
|
||||
(println "Connected to mongo at localhost:" db-name)
|
||||
{:conn conn
|
||||
:db db}))
|
||||
(defn recipe-tx [recipe]
|
||||
[{:db/id (d/tempid :db.part/user)
|
||||
:recipe/id (:id recipe)
|
||||
:recipe/name (:name recipe)
|
||||
:recipe/grubs (:grubs recipe)
|
||||
: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]
|
||||
(m/disconnect conn))
|
||||
(d/release conn))
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
(ns grub.util
|
||||
(:require #+clj [clojure.core.async :as a :refer [<! >! chan go]]
|
||||
#+cljs [cljs.core.async :as a :refer [<! >! chan]])
|
||||
#+cljs (:require-macros [grub.macros :refer [log logs]]
|
||||
[cljs.core.async.macros :refer [go]]))
|
||||
(:require #?(:clj [clojure.core.async :as a :refer [<! >! chan go]]
|
||||
:cljs [cljs.core.async :as a :refer [<! >! chan]]))
|
||||
#?(:cljs (:require-macros [grub.macros :refer [log logs]]
|
||||
[cljs.core.async.macros :refer [go]])))
|
||||
|
||||
(defn map-by-key [key coll]
|
||||
(->> coll
|
||||
|
@ -11,11 +11,11 @@
|
|||
|
||||
(defn printer []
|
||||
(let [in (chan)]
|
||||
(go (loop []
|
||||
(go (loop []
|
||||
(when-let [msg (<! printer)]
|
||||
#+clj (clojure.pprint/pprint msg)
|
||||
#+clj (println "-------")
|
||||
#+cljs (logs msg)
|
||||
#+cljs (log "-------")
|
||||
#?(:clj (do (clojure.pprint/pprint msg)
|
||||
(println "-------"))
|
||||
:cljs (do (logs msg)
|
||||
(log "-------")) )
|
||||
(recur))))))
|
||||
|
||||
|
|
Loading…
Reference in a new issue